Limpieza de datos
Creando el DataFrame
a partir de la variable Ingresos Totales (IT)
ITS <- filter(ITS, Año %in% c("2020","2021","2022"))
ITS %>% group_by(Año,Mes,Aeropuerto,Infraestructura) %>% summarise(IT = sum(`Importe por Servicios`)) -> DF
DF$IT[is.na(DF$IT)] <- 0
Uniendo la variable
Ingresos Regulados (IR)
IRS %>% group_by(Año,Mes,Aeropuerto) %>% summarise(IR = sum(`Importe por Servicios`)) -> IRegulados
DF <- merge(DF, IRegulados, by = c("Año","Mes","Aeropuerto"), all=TRUE)
DF$IR[is.na(DF$IR)] <- 0
Uniendo la variable
Numero de Pasajeros Internacionales (NPI)
PI <- filter(TP, `Tipo de Pasajero` == "INTERNACIONAL")
PI <- filter(PI,Año %in% c(2020,2021,2022))
PI <- select(PI, -Periodo)
PI <- select(PI, -`Tipo de Pasajero`)
DF <- merge(DF,PI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all = TRUE)
DF <- rename(DF, "NPI" = "Nro Pasajeros")
DF$NPI[is.na(DF$NPI)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Numero de Pasajeros Nacionales (NPN)
PN <- filter(TP, `Tipo de Pasajero` == "NACIONAL")
PN <- filter(PN,Año %in% c(2020,2021,2022))
PN <- select(PN, -Periodo)
PN <- select(PN, -`Tipo de Pasajero`)
DF <- merge(DF,PN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "NPN" = "Nro Pasajeros")
DF$NPN[is.na(DF$NPN)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso Rubro T U U A NACIONAL (TUUAN)
TUUAN <- filter(ITS, `Rubro Ingreso` == "T U U A NACIONAL")
TUUAN <- filter(TUUAN,Año %in% c(2020,2021,2022))
TUUAN <- select(TUUAN, -'Tipo Ingreso')
TUUAN <- select(TUUAN, -'Rubro Ingreso')
TUUAN <- select(TUUAN, -'Periodo')
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN_VER" = "Importe por Servicios")
DF <- merge(DF, TUUAN, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAN" = "Importe por Servicios")
DF$TUUAN_VER[is.na(DF$TUUAN_VER)] <- 0
DF$TUUAN_VER[DF$TUUAN_VER != 0] <- "Si"
DF$TUUAN_VER[DF$TUUAN_VER == "0"] <- "No"
DF$TUUAN[is.na(DF$TUUAN)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso Rubro T U U A INTERNACIONAL (TUUAI)
TUUAI <- filter(ITS, `Rubro Ingreso` == "T U U A INTERNACIONAL")
TUUAI <- filter(TUUAI,Año %in% c(2020,2021,2022))
TUUAI <- select(TUUAI, -'Tipo Ingreso')
TUUAI <- select(TUUAI, -'Rubro Ingreso')
TUUAI <- select(TUUAI, -'Periodo')
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI_VER" = "Importe por Servicios")#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, TUUAI, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "TUUAI" = "Importe por Servicios")
DF$TUUAI_VER[is.na(DF$TUUAI_VER)] <- 0
DF$TUUAI_VER[DF$TUUAI_VER != 0] <- "Si"
DF$TUUAI_VER[DF$TUUAI_VER == "0"] <- "No"
DF$TUUAI[is.na(DF$TUUAI)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso Rubro ATERRIZAJE Y DESPEGUE (IRAD)
IRAD <- filter(ITS, `Rubro Ingreso` == "ATERRIZAJE Y DESPEGUE")
IRAD <- filter(IRAD,Año %in% c(2020,2021,2022))
IRAD <- select(IRAD, -'Tipo Ingreso')
IRAD <- select(IRAD, -'Rubro Ingreso')
IRAD <- select(IRAD, -'Periodo')
DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRAD, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRAD" = "Importe por Servicios")
DF$IRAD_VER[is.na(DF$IRAD_VER)] <- 0
DF$IRAD_VER[DF$IRAD_VER != 0] <- "Si"
DF$IRAD_VER[DF$IRAD_VER == "0"] <- "No"
DF$IRAD[is.na(DF$IRAD)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso Rubro ALQUILER AREAS DE MANTENIMIENTO (AADM)
AADM <- filter(ITS, `Rubro Ingreso` == "ALQUILER AREAS DE MANTENIMIENTO")
AADM <- filter(AADM,Año %in% c(2020,2021,2022))
AADM <- select(AADM, -'Tipo Ingreso')
AADM <- select(AADM, -'Rubro Ingreso')
AADM <- select(AADM, -'Periodo')
DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AADM, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AADM" = "Importe por Servicios")
DF$AADM_VER[is.na(DF$AADM_VER)] <- 0
DF$AADM_VER[DF$AADM_VER != 0] <- "Si"
DF$AADM_VER[DF$AADM_VER == "0"] <- "No"
DF$AADM[is.na(DF$AADM)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso ALQUILER DE ESPACIOS PUBLICITSARIOS (ADEP)
ADEP <- filter(ITS, `Rubro Ingreso` == "ALQUILER DE ESPACIOS PUBLICITSARIOS")
ADEP <- filter(ADEP,Año %in% c(2020,2021,2022))
ADEP <- select(ADEP, -'Tipo Ingreso')
ADEP <- select(ADEP, -'Rubro Ingreso')
ADEP <- select(ADEP, -'Periodo')
DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ADEP, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADEP" = "Importe por Servicios")
DF$ADEP_VER[is.na(DF$ADEP_VER)] <- 0
DF$ADEP_VER[DF$ADEP_VER != 0] <- "Si"
DF$ADEP_VER[DF$ADEP_VER == "0"] <- "No"
DF$ADEP[is.na(DF$ADEP)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso ALQUILER LOCALES COMERCIALES (ALC)
ALC <- filter(ITS, `Rubro Ingreso` == "ALQUILER LOCALES COMERCIALES")
ALC <- filter(ALC,Año %in% c(2020,2021,2022))
ALC <- select(ALC, -'Tipo Ingreso')
ALC <- select(ALC, -'Rubro Ingreso')
ALC <- select(ALC, -'Periodo')
DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ALC, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ALC" = "Importe por Servicios")
DF$ALC_VER[is.na(DF$ALC_VER)] <- 0
DF$ALC_VER[DF$ALC_VER != 0] <- "Si"
DF$ALC_VER[DF$ALC_VER == "0"] <- "No"
DF$ALC[is.na(DF$ALC)] <- 0
#Reemplazo de N/A's por 0
Uniendo la variable
Ingreso Rubro ALQUILER OFICINAS OPERACIONES AEROLÍNEAS (AOOA)
AOOA <- filter(ITS, `Rubro Ingreso` == "ALQUILER OFICINAS OPERACIONES AEROLÍNEAS")
AOOA <- filter(AOOA,Año %in% c(2020,2021,2022))
AOOA <- select(AOOA, -'Tipo Ingreso')
AOOA <- select(AOOA, -'Rubro Ingreso')
AOOA <- select(AOOA, -'Periodo')
DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, AOOA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "AOOA" = "Importe por Servicios")
DF$AOOA_VER[is.na(DF$AOOA_VER)] <- 0
DF$AOOA_VER[DF$AOOA_VER != 0] <- "Si"
DF$AOOA_VER[DF$AOOA_VER == "0"] <- "No"
DF$AOOA[is.na(DF$AOOA)] <- 0
Uniendo la variable
Ingreso Rubro ALQUILERES DE ALMACEN/HANGAR (ADAH)
ADAH <- filter(ITS, `Rubro Ingreso` == "ALQUILERES DE ALMACEN/HANGAR")
ADAH <- filter(ADAH,Año %in% c(2020,2021,2022))
ADAH <- select(ADAH, -'Tipo Ingreso')
ADAH <- select(ADAH, -'Rubro Ingreso')
ADAH <- select(ADAH, -'Periodo')
DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, ADAH, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "ADAH" = "Importe por Servicios")
DF$ADAH_VER[is.na(DF$ADAH_VER)] <- 0
DF$ADAH_VER[DF$ADAH_VER != 0] <- "Si"
DF$ADAH_VER[DF$ADAH_VER == "0"] <- "No"
DF$ADAH[is.na(DF$ADAH)] <- 0
Uniendo la variable
Ingreso Rubro ESTACIONAMIENTO AERONAVES (IREA)
IREA <- filter(ITS, `Rubro Ingreso` == "ESTACIONAMIENTO AERONAVES")
IREA <- filter(IREA,Año %in% c(2020,2021,2022))
IREA <- select(IREA, -'Tipo Ingreso')
IREA <- select(IREA, -'Rubro Ingreso')
IREA <- select(IREA, -'Periodo')
DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IREA, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IREA" = "Importe por Servicios")
DF$IREA_VER[is.na(DF$IREA_VER)] <- 0
DF$IREA_VER[DF$IREA_VER != 0] <- "Si"
DF$IREA_VER[DF$IREA_VER == "0"] <- "No"
DF$IREA[is.na(DF$IREA)] <- 0
Uniendo la variable
Ingreso Rubro INGRESOS FINANCIEROS (IRIF)
IRIF <- filter(ITS, `Rubro Ingreso` == "INGRESOS FINANCIEROS")
IRIF <- filter(IRIF,Año %in% c(2020,2021,2022))
IRIF <- select(IRIF, -'Tipo Ingreso')
IRIF <- select(IRIF, -'Rubro Ingreso')
IRIF <- select(IRIF, -'Periodo')
DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRIF, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRIF" = "Importe por Servicios")
DF$IRIF_VER[is.na(DF$IRIF_VER)] <- 0
DF$IRIF_VER[DF$IRIF_VER != 0] <- "Si"
DF$IRIF_VER[DF$IRIF_VER == "0"] <- "No"
DF$IRIF[is.na(DF$IRIF)] <- 0
Uniendo la variable
Ingreso Rubro REEMBOLSOS (IRR)
IRR <- filter(ITS, `Rubro Ingreso` == "REEMBOLSOS")
IRR <- filter(IRR,Año %in% c(2020,2021,2022))
IRR <- select(IRR, -'Tipo Ingreso')
IRR <- select(IRR, -'Rubro Ingreso')
IRR <- select(IRR, -'Periodo')
IRR <- filter(IRR, `Importe por Servicios` != 0)
DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR_VER" = "Importe por Servicios")
#Creación de variable de verificación para reemplazo de N/A's
DF <- merge(DF, IRR, by = c("Año","Mes","Aeropuerto","Infraestructura"), all=TRUE)
DF <- rename(DF, "IRR" = "Importe por Servicios")
DF$IRR_VER[is.na(DF$IRR_VER)] <- 0
DF$IRR_VER[DF$IRR_VER != 0] <- "Si"
DF$IRR_VER[DF$IRR_VER == "0"] <- "No"
DF$IRR[is.na(DF$IRR)] <- 0
Agregando la
variable Numero de Pasajeros Totales (NP)
DF %>% mutate(NP = NPN + NPI) -> DF
#Numero de pasajeros totales
Eliminación de datos
y arreglos
# Si es que no tenemos el nombre del aeropuerto o su infraestructura (Siempre debe venir acompañada del nombre), la unidad muestral no podrá entrar al análisis pues por ejemplo si nos dicen cuanto gano un aeropuerto desconocido, esto no nos dirá nada.
DF$Mes = factor(DF$Mes, levels =c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Setiembre","Octubre","Noviembre","Diciembre"))
DF <- arrange(DF, Año, Mes)
DF$Aeropuerto[DF$Aeropuerto == 'No precisa'] <- NA
DF$Aeropuerto[DF$Aeropuerto == '-'] <- NA
DF$Infraestructura[DF$Infraestructura == '-'] <- NA
DF <- filter(DF, Infraestructura != is.na("Infraestructura") & Aeropuerto != is.na("Aeropuerto"))
DF %>% mutate("Entidad_Infraestructura" =
ifelse(Infraestructura=="ADP", "Aeropuertos del Perú S.A.",
ifelse(Infraestructura=="AAP", "Aeropuertos Andinos del Perú S.A.",
ifelse(Infraestructura=="COR", "CORPAC S.A.",
ifelse(Infraestructura=="LAP", "Lima Airport Partners S.R.L.",Infraestructura))))) -> DF
sum(complete.cases(DF))
[1] 378
DF$Mes = factor(DF$Mes, levels =c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Setiembre","Octubre","Noviembre","Diciembre"))
DF <- arrange(DF, Año, Mes)
Exportando la base
de datos
write_csv(DF,"BaseLimpiav2.csv")
Importando la base
datos limpia
rm(list = ls())
library(readr)
library(plyr)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:plyr’:
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(plotrix)
library(ggplot2)
library(stringi)
library(plotly)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following objects are masked from ‘package:plyr’:
arrange, mutate, rename, summarise
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library(MASS)
Attaching package: ‘MASS’
The following object is masked from ‘package:plotly’:
select
The following object is masked from ‘package:dplyr’:
select
DF <- read_csv("BaseLimpiav2.csv")
Rows: 1148 Columns: 34── Column specification ───────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (16): Mes, Aeropuerto, Infraestructura, TUUAN_VER, TUUAI_VER, IRAD_VER, AADM_VER, ADEP_VER, ALC_VER...
dbl (18): Año, IT, IR, NPI, NPN, TUUAN, TUUAI, IRAD, AADM, ADEP, ALC, AOOA, ADAH, AEHE, IREA, IRIF, IRR...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Variables
Año: Variable categórica que indica el año de la
recolección de información.
Mes: Variable categórica que indica el mes de la
recolección de información.
Aeropuerto: Variable cualitativa que indica el
aeropuerto del cual se recolecta la información
Infraestructura: Variable cualitativa que indica en
acrónimo a que entidad pertenece la infraestructura del aeropuerto del
cual se recolecta la información.
Entidad_Infraestructura: Variable cualitativa que
indica a que entidad pertenece la infraestructura del aeropuerto del
cual se recolecta la información.
IT: Variable cuantitativa que representa los
ingresos totales en dolares que ha registrado el aeropuerto
IR: Variable cuantitativa que representa los
ingresos regulados en dolares que ha registrado el aeropuerto
TUUAN: Variable cuantitativa que representa el
ingreso en dolares que ha generado la TARIFA UNIFICADA POR USO DE
AEROPUERTO de tipo nacional.
TUUAN: Variable cuantitativa que representa el
ingreso en dolares que ha generado la TARIFA UNIFICADA POR USO DE
AEROPUERTO de tipo internacional.
NPI: Variable cuantitativa que representa el numero
de pasajeros internacionales que ha registrado el aeropuerto
NPN: Variable cuantitativa que representa el numero
de pasajeros nacionales que ha registrado el aeropuerto
IRAD_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por aterrizaje y despegue.
IRAD: Variable cuantitativa que representa el
ingreso en dolares del aeropuerto por aterrizaje y despegue.
AADM_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el alquiler de áreas de
mantenimiento.
AADM: Variable cuantitativa que representa el
ingreso en dolares por el alquiler de áreas de mantenimiento.
ADEP_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el alquiler de espacios de
publicidad.
ADEP: Variable cuantitativa que representa el
ingreso en dolares por el alquiler de espacios de publicidad.
ALC_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el alquiler de locales comerciales.
ALC: Variable cuantitativa que representa el ingreso
en dolares por el alquiler de locales comerciales.
AOOA_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el alquiler de oficinas de operaciones
de aerolíneas.
AOOA: Variable cuantitativa que representa el
ingreso en dolares por el alquiler de oficinas de operaciones de
aerolíneas.
ADAH_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el alquiler de almacenes/hangares.
ADAH: Variable cuantitativa que representa el
ingreso en dolares por el alquiler de almacenes/hangares.
AEHE_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por la atención en horas extras.
AEHE: Variable cuantitativa que representa el
ingreso en dolares por la atención en horas extras.
IREA_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por el estacionamiento de aeronaves.
IREA: Variable cuantitativa que representa el
ingreso en dolares por el estacionamiento de aeronaves.
IRIF_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por reembolso en ingresos financieros.
IRIF: Variable cuantitativa que representa el
ingreso en dolares por reembolso en ingresos financieros.
IRR_VER: Variable categórica que representa si el
aeropuerto obtiene ingresos por reembolsos.
IRR: Variable cuantitativa que representa el ingreso
en dolares por reembolsos.
NP: Variable cuantitativa que representa el numero
de pasajeros totales que ha registrado el aeropuerto.
Descriptores
Numéricos
cv <- function(x){
return(sd(x, na.rm=T)/mean(x, na.rm=T))
}
tabla <- data.frame(Variables = c('IT', 'NPN', 'NPI', 'TUUAN','TUUAI'),
Media = c(mean(DF$IT, na.rm=T),
mean(DF$NPN, na.rm = T),
mean(DF$NPI, na.rm= T),
mean(DF$TUUAN, na.rm= T),
mean(DF$TUUAI, na.rm= T)),
Mediana = c(median(DF$IT, na.rm=T),
median(DF$NPN, na.rm = T),
median(DF$NPI, na.rm= T),
median(DF$TUUAN, na.rm = T),
median(DF$TUUAI, na.rm= T)),
Desviacion = c(sd(DF$IT, na.rm=T),
sd(DF$NPN, na.rm = T),
sd(DF$NPI, na.rm= T),
sd(DF$TUUAN, na.rm = T),
sd(DF$TUUAI, na.rm= T)),
Varianza = c(var(DF$IT, na.rm = T),
var(DF$NPN, na.rm = T),
var(DF$NPI, na.rm = T),
var(DF$TUUAN, na.rm = T),
var(DF$TUUAI, na.rm = T)),
RangoIntercuartil = c(IQR(DF$IT, na.rm = T),
IQR(DF$NPN, na.rm = T),
IQR(DF$NPI, na.rm = T),
IQR(DF$TUUAN, na.rm = T),
IQR(DF$TUUAI, na.rm = T)),
CoeficienteVariacion = c(cv(DF$IT),
cv(DF$NPN),
cv(DF$NPI),
cv(DF$NPN),
cv(DF$NPI)))
tabla
De la tabla podemos conseguir la siguiente información:
La escala con la que se trabaja es bastante grande, de ahí el
hecho que la varianza y desviación sean tan grande.
Tanto la varianza como la desviación nos indican que los datos de
los Ingresos Totales, el Numero de Pasajeros Nacionales y el Numero de
Pasajeros Internacionales están muy dispersos.
Se aprecia un fenómeno que la mediana y el rango intercuartil de
la variable Pasajeros internacionales es 0. Esto quiere decir que hay
muchos aeropuertos los cuales no suelen recibir pasajeros
internacionales.
Descriptores
Gráficos
Numero de Pasajeros
vs Ingresos Totales
plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))

Comenzamos comparando el numero de pasajeros en miles totales, suma
de pasajeros internacionales y nacionales, con los ingresos totales de
cada aeropuerto en determinado mes y año en millones de dolares. A
simple vista se puede ver un cierto tipo de relación lineal, sin embargo
tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que
este no toma en cuenta la escala de las unidades, perfecto para nuestro
estudio.
cor(DF$IT, DF$NP, use="complete.obs")
[1] 0.9834118
Con la información suministrada del coeficiente de correlación se
deduce que la relación lineal entre el numero de pasajeros y los
ingresos totales es buena, casi perfecta y ascendente. Es decir los
ingresos totales aumentaran en cuanto aumente el numero de
pasajeros.
Ahora crearemos un modelo de regresión lineal.
modelo = lm(DF$IT ~ DF$NP, data=DF)
modelo
Call:
lm(formula = DF$IT ~ DF$NP, data = DF)
Coefficients:
(Intercept) DF$NP
-151042.68 16.46
d <- data.frame("X"=DF$NP/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
-0.15104 0.01646
Hemos creado dos modelos que en realidad son el mismo pero a
diferentes escalas. El primero nos sirve para usar directamente el
numero de pasajeros y los ingresos totales en dolares. El segundo para
usar el numero de pasajeros en miles y conseguir los ingresos totales en
millones de dolares. Ambos modelos nos permiten aproximar, predecir los
ingresos totales de un aeropuerto en determinado mes y año usando la
cantidad de pasajeros totales que llevo en el mismo lapso de tiempo.
plot(DF$NP/1000, DF$IT/1000000, xlab = "Numero de pasajeros (miles)", ylab = "Ingresos totales (millones de US$)", col="darkgreen", pch="•", xlim = c(0,2000))
abline(a= -0.14890, b=0.01646, col="green")

Numero de Pasajeros
Nacionales e Internacionales vs Ingresos Totales
par(mfrow=c(1,2))
plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")
plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")

Ahora vamos a analizar la relación de los tipos de pasajeros con los
ingresos totales. De nuevo usaremos el coeficiente de correlación tanto
para los pasajeros nacionales como internacionales.
cor(DF$IT, DF$NPN, use="complete.obs")
[1] 0.9738777
cor(DF$IT, DF$NPI, use="complete.obs")
[1] 0.9783331
De los coeficientes dados se encuentra que:
- Ambos demuestran que tanto los pasajeros nacionales como
internacionales poseen una buena y ascendente relación lineal con los
ingresos totales.
- Ambos son menores al cor de los pasajeros totales
con los ingresos totales. Indica que si se usa solo a los pasajeros
nacionales o solo a los internacionales para aproximar los ingresos
totales, se tendrá una precisión menor a que si se usará la suma de
ambos.
- El cor de los pasajeros internacionales es
ligeramente superior al de los pasajeros nacionales, mostrando que su
relación lineal con los ingresos totales es ligeramente más acorde que
la relación lineal de los pasajeros nacionales.
Ahora construyamos los modelos de regresión lineal para cada uno.
modelo = lm(DF$IT ~ DF$NPN, data=DF)
modelo
Call:
lm(formula = DF$IT ~ DF$NPN, data = DF)
Coefficients:
(Intercept) DF$NPN
-363490.18 24.52
d <- data.frame("X"=DF$NPN/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
-0.36349 0.02452
modelo = lm(DF$IT ~ DF$NPI, data=DF)
modelo
Call:
lm(formula = DF$IT ~ DF$NPI, data = DF)
Coefficients:
(Intercept) DF$NPI
319864.95 47.72
d <- data.frame("X"=DF$NPI/1000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
0.31986 0.04772
rm(d)
Vemos que los modelos difieren en una cantidad considerable en cuanto
a su pendiente, sin embargo, su intercepto es bastante similar, vamos a
graficar estos modelos.
par(mfrow=c(1,2))
plot(DF$NPN/1000, DF$IT/1000000, xlab = "Numero de pasajeros nacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="red", pch="•")
abline(a= -0.36033, b=0.02451, col="#f72585")
plot(DF$NPI/1000, DF$IT/1000000, xlab = "Numero de pasajeros internacionales (miles)", ylab = "Ingresos totales (millones de US$)", col="blue", pch="•")
abline(a= 0.31996, b=0.04772, col="#0077b6")

Analizando la
distribución de Ingresos Totales
plot_ly(x = ~DF$IT/1000000,
type="histogram",
color = ~DF$Infraestructura,
nbinsx = 100
)%>%
layout(yaxis = list( title = "Frecuencia" ),
xaxis = list( title = "Ingresos totales (Millones de US$)",
nticks = 20))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations
Gracias al histograma se dice que los datos de los ingresos totales
son totalmente asimétricos y se encuentran acumulados en un intervalo de
0 - 0.5 millones de dolares. Es decir la mayoría de aeropuertos
determinados en cierto mes y cierto año posee unos ingresos totales de
entre 0 y 0.5 millones de dolares. Esto puede ocurrir debido a datos
atípicos, construyamos un Boxplot para que nos ayude.
plot_ly(DF, x=~DF$IT/1000000,
type = "box")%>%
layout(
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations
Usando un Boxplot simple se comprueba como los datos de los ingresos
totales están demasidos dispersos gracias a cierta cantidad de datos
atipicos. Ahora es necesario averiguar de donde provienen estos datos
atípicos y que nos quieren decir. Para ello crearemos diferentes
Boxplots basados en meses, infraestructuras y aeropuertos.
plot_ly(DF, x = ~IT/1000000,
y = ~Mes,
color= ~Mes,
type="box") %>%
layout(yaxis = list( title = "Mes"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Con este gráfico podemos descartar que los datos atípicos provengan
de un o varios meses en específico.
plot_ly(DF, x = ~IT/1000000,
y = ~Infraestructura,
color= ~Entidad_Infraestructura,
type="box") %>%
layout(yaxis = list( title = "Infraestructura"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: Ignoring 395 observations
En este gráfico se observa como Lima Airport Partners S.R.L rebasa
por mucho a las otras infraestructuras en cuanto a ingresos totales se
refiere. Aquí podemos ya saber que esos datos atípicos de ingresos están
generados en su gran mayoría por la infraestructura Lima Airport
Partners S.R.L. Además es importante mencionar que la infraestructura
COR no aparece en la gráfica pues no ha declarado ningún ingreso
total.
plot_ly(DF, x = ~IT/1000000,
y = ~Aeropuerto,
color= ~Aeropuerto,
type="box"
) %>%
layout(yaxis = list( title = "Aeropuertos"),
xaxis = list( title = "Ingresos totales (Millones de US$)"))
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Gracias a los 3 gráficos podemos concluir que:
- El aeropuerto de Lima cuya entidad prestadora es la LAP, es la
responsable de los datos atípicos y además es el que más ingresos
totales genera.
- La infraestructura LAP trabaja en Lima y se refiere al Aeropuerto
Internacional Jorge Chávez. Esto nos quiere decir que en el Perú, el
aeropuerto que genera más ingresos es el Jorge Chávez.
Numero de Pasajeros
vs Aeropuertos
plot_ly(DF,y = ~NP/1000,
x = ~as.factor(Aeropuerto),
type="bar",
marker = list(color=c("lightblue"))
)%>%
layout(xaxis = list( title = "Aeropuertos"),
yaxis = list( title = "Numero de pasajeros (miles)"))
Con esta gráfico se corrobora que el Aeropuerto de Lima (Aeropuerto
Internacional Jorge Chávez) genera la mayor cantidad de ingresos y
además recibe a la mayor cantidad de pasajeros respecto al resto del
Perú. Otros aeropuertos notables son Cusco, Arequipa e Iquitos donde
Cusco es el que más pasajeros recibe fuera de Lima. Se procede a dibujar
el numero de pasajeros, los ingresos totales y los aeropuertos.
plot_ly(DF,x = ~NP/1000,
y = ~IT/1000000,
type="scatter",
color = ~as.factor(Aeropuerto)
)
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
No scatter mode specifed:
Setting the mode to markers
Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Warning: Ignoring 395 observationsWarning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
Warning: n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors
El gráfico nos deja en claro la estrecha relación de la cantidad de
pasajeros con la de ingresos que posee el aeropuerto de Lima y como este
sobresale por mucho del resto de aeropuertos. Se concluye que los datos
atípicos provenientes de ingresos totales eran y nos contaban sobre las
peculiaridades del caso Lima.
Ingresos T U U A
Total vs Ingresos Totales
Se eligió la comparación de las T U U A, porque esta es la TARIFA
UNIFICADA POR USO DE AEROPUERTO, es decir es una tarifa que como
consumidores debemos de pagar. El objetivo aquí es analizar cuanto de
los ingresos totales provienen directamente de los bolsillos de los
pasajeros.
plot((DF$TUUAN/1000000 + DF$TUUAI/1000000), DF$IT/1000000, xlab = "Ingresos por TUUA (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")

Comenzamos comparando el numero de pasajeros en miles totales, suma
de pasajeros internacionales y nacionales, con los ingresos totales de
cada aeropuerto en determinado mes y año en millones de dolares. A
simple vista se puede ver un cierto tipo de relación lineal, sin embargo
tenemos que comprobarlo. Usaremos el coeficiente de correlación ya que
este no toma en cuenta la escala de las unidades, perfecto para nuestro
estudio.
cor(DF$IT, DF$TUUAI + DF$TUUAN, use="complete.obs")
[1] 0.9870129
Tenemos un coeficiente de correlación que esta muy próximo a 1, es
decir esta relación es casi perfectamente lineal y con tendencia
ascendente.
Ahora crearemos un modelo de regresión lineal.
TUUA <- DF$TUUAI+DF$TUUAN
modelo = lm(DF$IT ~ TUUA, data=DF)
modelo
Call:
lm(formula = DF$IT ~ TUUA, data = DF)
Coefficients:
(Intercept) TUUA
155740.38 2.19
d <- data.frame("X"= (DF$TUUAI + DF$TUUAN)/100000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
0.1557 0.2190
rm(d)
Del modelo creado se obtiene el intercepto, es decir cuando la TUUA
valdrá cero y la pendiente, en este caso es relativamente baja pero
ascendente.
plot(TUUA/100000, DF$IT/1000000, xlab = "TUUA total (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#926c15", pch="•")
abline(a= 0.1557, b=0.2190, col="#c9a227")

Ingresos TUUA
Nacional y TUUA Internacional vs Ingresos Totales
par(mfrow=c(1,2))
plot(DF$TUUAN/1000000, DF$IT/1000000, xlab = "Ingresos TUUA nacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#f8961e", pch="•")
plot(DF$TUUAI/1000000, DF$IT/1000000, xlab = "Ingresos TUUA internacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#90be6d", pch="•")

Probemos de nuevo a usar el coeficiente de correlación para ambas
variables
cor(DF$IT, DF$TUUAN, use="complete.obs")
[1] 0.985771
cor(DF$IT, DF$TUUAI, use="complete.obs")
[1] 0.9760972
De los coeficientes dados se encuentra que:
- Los dos coeficientes muestran una casi perfecta linealidad
ascendente.
- Ninguno de los dos cor por separado pudo superar al
anterior visto producto de la suma de las TUUA.
- El cor nacional es ligeramente superior al
cor internacional.
Ahora construyamos los modelos de regresión lineal para cada uno.
modelo = lm(DF$IT ~ DF$TUUAN, data=DF)
modelo
Call:
lm(formula = DF$IT ~ DF$TUUAN, data = DF)
Coefficients:
(Intercept) DF$TUUAN
-59899.076 5.213
d <- data.frame("X"=DF$TUUAN/1000000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
-0.0599 5.2126
modelo = lm(DF$IT ~ DF$TUUAI, data=DF)
modelo
Call:
lm(formula = DF$IT ~ DF$TUUAI, data = DF)
Coefficients:
(Intercept) DF$TUUAI
3.295e+05 3.688e+00
d <- data.frame("X"=DF$TUUAI/1000000, "Y"=DF$IT/1000000)
modelo = lm(d$Y ~ d$X, data=d)
modelo
Call:
lm(formula = d$Y ~ d$X, data = d)
Coefficients:
(Intercept) d$X
0.3295 3.6882
rm(d)
Los modelos poseen bastantes diferencias entre sí como sus
interceptos que a simple no tienen nada en común al igual que sus
pendientes. Veamoslo en una grafica.
par(mfrow=c(1,2))
plot(DF$TUUAN/1000000, DF$IT/1000000, xlab = "Ingresos TUUA nacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#f8961e", pch="•")
abline(a= -0.0599, b=5.2126, col="#f3722c")
plot(DF$TUUAI/1000000, DF$IT/1000000, xlab = "Ingresos TUUA internacional (millones de US$)", ylab = "Ingresos totales (millones de US$)", col="#90be6d", pch="•")
abline(a= 0.3295, b=3.6882, col="#43aa8b")

Detallamos entonces que los ingresos totales guardan una alta
relación con los ingresos generados por las TUUA y dependen en gran
medida de estas, ergo la cantidad de pasajeros.
Pandemia vs
PostPandemia
DF2020 <- filter(DF, DF$Año=="2020")
DF2021 <- filter(DF, DF$Año=="2021")
DF2022 <- filter(DF, DF$Año=="2022")
DF2020 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2020
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
DF2021 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2021
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
DF2022 %>% group_by(Mes,Año) %>% summarise(IT = sum(IT, na.rm=TRUE), NP = sum(NP, na.rm = TRUE)) -> DF2022
`summarise()` has grouped output by 'Mes'. You can override using the `.groups` argument.
plot_ly(y = ~DF2020$IT/1000000,
x = ~DF2020$Mes,
type="bar",
name="2020",
marker = list(color = '#57cc99')
)%>%
add_trace(y = ~DF2021$IT/1000000,
x = ~DF2021$Mes,
type="bar",
name="2021",
marker = list(color = '#38a3a5')
)%>%
add_trace(y = ~DF2022$IT/1000000,
x = ~DF2022$Mes,
type="bar",
name="2022",
marker = list(color = '#22577a')
)%>%
layout(xaxis = list( title = "Meses"),
yaxis = list( title = "Ingresos totales (Millones de US$)",
nticks = 10,
range = list(0,45)),
barmode="group")
Del gráfico de barras podemos observar:
La distribución de los ingresos totales en base a los meses del
año.
Existe una asimetria notable entre los datos en el año 2020. Esta
asimetria se explica por el surgimiento del Covid-19. Los ingresos
bajaron bastante en proporción a la media.
Un patrón de crecimiento sobre los ingresos totales dependiendo
de los meses. En algunos meses los ingresos totales son esperado a ser
mayores que en otros meses, uno de los factores que pueden influir en
esto son las vacaciones pues están estrechamente relacionas con el
número de pasajeros a abordarr en un aeropuerto.
plot_ly() %>%
add_trace(y = ~DF2020$IT/1000000,
x = ~DF2020$Mes,
type="scatter",
mode="lines+markers",
name="2020",
marker = list(color = '#57cc99'),
line = list(color = '#57cc99'),
fill = "tonexty",
fillcolor = 'rgba(197,237,211,0.3)'
)%>%
add_trace(DF2021, y = ~DF2021$IT/1000000,
x = ~DF2021$Mes,
type="scatter",
mode="lines+markers",
name="2021",
marker = list(color = '#38a3a5'),
line = list(color = '#38a3a5'),
fill = "tonexty",
fillcolor = 'rgba(106,166,169,0.3)'
)%>%
add_trace(y = ~DF2022$IT/1000000,
x = ~DF2022$Mes,
type="scatter",
mode="lines+markers",
name="2022",
marker = list(color = '#22577a'),
line = list(color = '#22577a'),
fill = "tonexty",
fillcolor = 'rgba(68,102,122,0.3)'
)%>%
layout(xaxis = list( title = "Meses"),
title = "Evolutivo Ingresos",
yaxis = list( title = "Ingresos totales (Millones de US$)",
range = list(0,45))
)
NA
plot_ly() %>%
add_trace(y = ~DF2020$NP/1000,
x = ~DF2020$Mes,
type="scatter",
mode="lines+markers",
name="2020",
marker = list(color = '#E09F3E'),
line = list(color = '#E09F3E'),
fill = "tonexty",
fillcolor = 'rgba(225,183,123,0.3)'
)%>%
add_trace(DF2021, y = ~DF2021$NP/1000,
x = ~DF2021$Mes,
type="scatter",
mode="lines+markers",
name="2021",
marker = list(color = '#9E2A2B'),
line = list(color = '#9E2A2B'),
fill = "tonexty",
fillcolor = 'rgba(158,72,74,0.3)'
)%>%
add_trace(y = ~DF2022$NP/1000,
x = ~DF2022$Mes,
type="scatter",
mode="lines+markers",
name="2022",
marker = list(color = '#540B0E'),
line = list(color = '#540B0E'),
fill = "tonexty",
fillcolor = 'rgba(87,45,47,0.3)'
)%>%
layout(xaxis = list( title = "Meses"),
title = "Evolutivo Pasajeros",
yaxis = list( title = "Numero de Pasajeros (Miles)"))
De los gráficos evolutivos podemos apreciar:
Como es el comportamiento de los ingresos totales frente a los
meses y a los años marcados por la pandemia.
En el mes de Febrero del año 2020 comienza una caída drástica en
los ingresos hasta Abril del mismo año donde comienza a estabilizarse.
Este periodo coincide con la aparición del Covid-19 en Perú y el
establecimiento de las medidas de confinamiento. El confinamiento indica
que el número de pasajeros se reduce en gran proporción. Esta causa
también se puede observar en el evolutivo de pasajeros y el como su
número de cae hasta 0 o casi 0. Los aeropuerto tuvieron consecuencias
que tardaron mucho en disiparse Muestra de ello es como se tardó 2 años
y 5 meses para volver a un punto similar al de Febrero 2020 en ingresos
totales.
```r
round(100 - ((filter(DF2020, Mes == "Abril")$IT/1000000 )/( filter(DF2020, Mes == "Febrero")$IT/1000000) * 100) ,2)
```
```
[1] 86.68
```
```r
round( - filter(DF2020, Mes == "Abril")$IT/1000000 + filter(DF2020,Mes == "Febrero")$IT/1000000, 2)
```
```
[1] 31.67
```
La pérdida del mes de Abril del 2020 respecto al mes de Febrero
del 2020 fue del 86.68% suponiendo una diferencia de 31.76 millones de
dolares.
A partir del mes de Abril se estabilizan los ingresos del año
2020. Estos son bajos pero se observa una tendencia ascendente.
Tendencia que continua en los años 2021 y 2022 a medida que el
confinamiento se levanta, la pandemia se controla y el numero de
pasajeros aumenta.
Conclusión
A razón de resumen, en nuestro análisis sobre la relación entre el
número de pasajeros y los ingresos totales de los aeropuertos graficamos
la distribución de los ingresos totales, las diferentes relaciones entre
variables tales como la última vista (Ingresos TUUA vs Ingresos
Totales), (cantidad de pasajeros y aeropuertos). Asimismo observamos y
describimos el comportamiento evolutivo de los ingresos totales respecto
a los años vividos en pandemia y post-pandemia. Finalemnte, con la
información recolectada y el estudio realizado se encontró que los
ingresos totales generados por los aeropuertos en el Perú dependente
altamente en los consumidores o pasajeros, siendo la TUUA el ejemplo más
claro de ello.
LS0tDQp0aXRsZTogIkVzdGFkaXN0aWNhcyBzb2JyZSBsb3MgYWVyb3B1ZXJ0b3MiDQphdXRob3I6ICJHcnVwbyA3LCBTZWNjacOzbiA5Ig0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIg0KZWRpdG9yOiB2aXN1YWwNCmZvcm1hdDogaHRtbA0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQojICoqQWx1bW5vcyBkZWwgZ3J1cG86KioNCg0KfCBBbHVtbm8gICAgICAgICAgICAgICAgICAgICAgICAgIHwgKipDw7NkaWdvKiogICAgfCAqKkNvcnJlbyoqICAgICAgICAgICAgICAgICAgICAgfCAqKlBvcmNlbnRhamUgZGUgVHJhYmFqbyoqIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgKioqU2FtaXIgU3RlZmFubyBTdWFyZXogUmlvcyoqKiB8ICoqMjAyMjEwNjExKiogfCAqKnNhbWlyLnN1YXJlelxAdXRlYy5lZHUucGUqKiAgfCAqKnglKiogICAgICAgICAgICAgICAgICAgIHwNCnwgKipNaWx0b24gRXN0ZWJhbiBSb2JsZXMgUmV5ZXMqKiB8ICoqMjAyMjEwNDE2KiogfCAqKm1pbHRvbi5yb2JsZXNcQHV0ZWMuZWR1LnBlKiogfCAqKnglKiogICAgICAgICAgICAgICAgICAgIHwNCnwgKipDYWJhbGxpdG8gSHVydGFkbyoqICAgICAgICAgICB8ICoqMjAxNjEwMDAyKiogfCAqKk1hcsOtYS5zYWxpbmFzXEB1dGVjLmVkdS5wZSoqIHwgKip4JSoqICAgICAgICAgICAgICAgICAgICB8DQp8ICoqQ2hyaXNzIE1hcnRpbiBkZSBDb2xkcGxheSoqICAgfCAqKjIwMTYxMDAwMioqIHwgKipNYXLDrWEuc2FsaW5hc1xAdXRlYy5lZHUucGUqKiB8ICoqeCUqKiAgICAgICAgICAgICAgICAgICAgfA0KDQojICoqVGVtYSoqDQoNCkFuw6FsaXNpcyBtZW5zdWFsIGRlIGxhIHJlbGFjacOzbiBlbnRyZSBuw7ptZXJvIGRlIHBhc2FqZXJvcyBlIGluZ3Jlc29zIHRvdGFsZXMgcG9yIGFlcm9wdWVydG8gKDIwMjAtMjAyMikNCg0KIyAqKk9iamV0aXZvKioNCg0KRXZhbHVhciBsYSBpbmZsdWVuY2lhIGRlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBlbiBsb3MgaW5ncmVzb3MgdG90YWxlcyAoXCQpIHBvciBtZXMgeSBhw7FvIGVuIGNhZGEgYWVyb3B1ZXJ0byBlbiBlbCBQZXLDui4NCg0KIyMgT2JqZXRpdm8gU2VjdW5kYXJpb3MNCg0KLSAgIERldGVybWluYXIgZWwgYWVyb3B1ZXJ0byBjb24gbWF5b3IgYWZsdWVuY2lhIGRlIHBhc2FqZXJvcyB5IGVsIGRlIG1heW9yIGluZ3Jlc29zIGRlbCBQZXLDui4NCg0KLSAgIENvbXBhcmFyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIChcJCkgZGUgbG9zIHJ1YnJvcyAoVCBVIFUgQSBOYWNpb25hbCwgVCBVIFUgQSBJbnRlcm5hY2lvbmFsICkgZW4gbG9zIGFlcm9wdWVydG9zIGRlbCBQZXLDui4NCg0KLSAgIENvbXBhcmFyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIChcJCkgZHVyYW50ZSBsYSBwYW5kZW1pYSB5IHBvc3QgcGFuZGVtaWEgZW4gZWwgUGVyw7ouDQoNCiMjIFRhYmxhIGRlIHZhcmlhYmxlcw0KDQojIExpYnJlcsOtYXMNCg0KYGBge3IgZWNobz1GQUxTRX0NCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJlYWRyKQ0Kcm0obGlzdD1scygpKQ0KYGBgDQoNCiMgVGFibGFzDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpJVFMgPC0gcmVhZF9jc3YoIlJlY2F1ZGFjaW9uSW5ncmVzb3NUb3RhbGVzLmNzdiIpDQpJUlM8LSByZWFkX2NzdigiUmVjYXVkYWNpb25JbmdyZXNvc1JlZ3VsYWRvcy5jc3YiKQ0KVFAgPC0gcmVhZF9jc3YoIlRyYWZpY29QYXNhamVyb3MuY3N2IikNCmBgYA0KDQojIExpbXBpZXphIGRlIGRhdG9zDQoNCiMjIENyZWFuZG8gZWwgRGF0YUZyYW1lIGEgcGFydGlyIGRlIGxhIHZhcmlhYmxlIEluZ3Jlc29zIFRvdGFsZXMgKElUKQ0KDQpgYGB7ciBldmFsPVRSVUV9DQpJVFMgPC0gZmlsdGVyKElUUywgQcOxbyAlaW4lIGMoIjIwMjAiLCIyMDIxIiwiMjAyMiIpKQ0KSVRTICU+JSBncm91cF9ieShBw7FvLE1lcyxBZXJvcHVlcnRvLEluZnJhZXN0cnVjdHVyYSkgJT4lIHN1bW1hcmlzZShJVCA9IHN1bShgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCkpIC0+IERGDQoNCmBgYA0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KREYkSVRbaXMubmEoREYkSVQpXSA8LSAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvcyBSZWd1bGFkb3MgKElSKQ0KDQpgYGB7cn0NCklSUyAlPiUgZ3JvdXBfYnkoQcOxbyxNZXMsQWVyb3B1ZXJ0bykgJT4lIHN1bW1hcmlzZShJUiA9IHN1bShgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCkpIC0+IElSZWd1bGFkb3MNCkRGIDwtIG1lcmdlKERGLCBJUmVndWxhZG9zLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiksIGFsbD1UUlVFKQ0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpERiRJUltpcy5uYShERiRJUildIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIE51bWVybyBkZSBQYXNhamVyb3MgSW50ZXJuYWNpb25hbGVzIChOUEkpDQoNCmBgYHtyfQ0KUEkgPC0gZmlsdGVyKFRQLCBgVGlwbyBkZSBQYXNhamVyb2AgPT0gIklOVEVSTkFDSU9OQUwiKQ0KUEkgPC0gZmlsdGVyKFBJLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClBJIDwtIHNlbGVjdChQSSwgLVBlcmlvZG8pDQpQSSA8LSBzZWxlY3QoUEksIC1gVGlwbyBkZSBQYXNhamVyb2ApDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERixQSSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGwgPSBUUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiTlBJIiA9ICJOcm8gUGFzYWplcm9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiROUElbaXMubmEoREYkTlBJKV0gPC0gMA0KDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBOdW1lcm8gZGUgUGFzYWplcm9zIE5hY2lvbmFsZXMgKE5QTikNCg0KYGBge3J9DQpQTiA8LSBmaWx0ZXIoVFAsIGBUaXBvIGRlIFBhc2FqZXJvYCA9PSAiTkFDSU9OQUwiKQ0KUE4gPC0gZmlsdGVyKFBOLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClBOIDwtIHNlbGVjdChQTiwgLVBlcmlvZG8pDQpQTiA8LSBzZWxlY3QoUE4sIC1gVGlwbyBkZSBQYXNhamVyb2ApDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERixQTiwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIk5QTiIgPSAiTnJvIFBhc2FqZXJvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkTlBOW2lzLm5hKERGJE5QTildIDwtIDANCg0KI1JlZW1wbGF6byBkZSBOL0EncyBwb3IgMA0KYGBgDQoNCiMjIFVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBUIFUgVSBBIE5BQ0lPTkFMIChUVVVBTikNCg0KYGBge3J9DQpUVVVBTiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIlQgVSBVIEEgTkFDSU9OQUwiKQ0KVFVVQU4gPC0gZmlsdGVyKFRVVUFOLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClRVVUFOIDwtIHNlbGVjdChUVVVBTiwgLSdUaXBvIEluZ3Jlc28nKQ0KVFVVQU4gPC0gc2VsZWN0KFRVVUFOLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KVFVVQU4gPC0gc2VsZWN0KFRVVUFOLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzDQpERiA8LSBtZXJnZShERiwgVFVVQU4sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJUVVVBTl9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgVFVVQU4sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJUVVVBTiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRUVVVBTl9WRVJbaXMubmEoREYkVFVVQU5fVkVSKV0gPC0gMA0KREYkVFVVQU5fVkVSW0RGJFRVVUFOX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRUVVVBTl9WRVJbREYkVFVVQU5fVkVSID09ICIwIl0gPC0gIk5vIg0KREYkVFVVQU5baXMubmEoREYkVFVVQU4pXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIFQgVSBVIEEgSU5URVJOQUNJT05BTCAoVFVVQUkpDQoNCmBgYHtyfQ0KVFVVQUkgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJUIFUgVSBBIElOVEVSTkFDSU9OQUwiKQ0KVFVVQUkgPC0gZmlsdGVyKFRVVUFJLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNClRVVUFJIDwtIHNlbGVjdChUVVVBSSwgLSdUaXBvIEluZ3Jlc28nKQ0KVFVVQUkgPC0gc2VsZWN0KFRVVUFJLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KVFVVQUkgPC0gc2VsZWN0KFRVVUFJLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIFRVVUFJLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQUlfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKSNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIFRVVUFJLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiVFVVQUkiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KDQpERiRUVVVBSV9WRVJbaXMubmEoREYkVFVVQUlfVkVSKV0gPC0gMA0KREYkVFVVQUlfVkVSW0RGJFRVVUFJX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRUVVVBSV9WRVJbREYkVFVVQUlfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkVFVVQUlbaXMubmEoREYkVFVVQUkpXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFURVJSSVpBSkUgWSBERVNQRUdVRSAoSVJBRCkNCg0KYGBge3J9DQpJUkFEIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQVRFUlJJWkFKRSBZIERFU1BFR1VFIikNCklSQUQgPC0gZmlsdGVyKElSQUQsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJBRCA8LSBzZWxlY3QoSVJBRCwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJBRCA8LSBzZWxlY3QoSVJBRCwgLSdSdWJybyBJbmdyZXNvJykNCklSQUQgPC0gc2VsZWN0KElSQUQsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUkFELCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJBRF9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUkFELCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJBRCIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJElSQURfVkVSW2lzLm5hKERGJElSQURfVkVSKV0gPC0gMA0KREYkSVJBRF9WRVJbREYkSVJBRF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkSVJBRF9WRVJbREYkSVJBRF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRJUkFEW2lzLm5hKERGJElSQUQpXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFMUVVJTEVSIEFSRUFTIERFIE1BTlRFTklNSUVOVE8gKEFBRE0pDQoNCmBgYHtyfQ0KQUFETSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIEFSRUFTIERFIE1BTlRFTklNSUVOVE8iKQ0KQUFETSA8LSBmaWx0ZXIoQUFETSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBQURNIDwtIHNlbGVjdChBQURNLCAtJ1RpcG8gSW5ncmVzbycpDQpBQURNIDwtIHNlbGVjdChBQURNLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQUFETSA8LSBzZWxlY3QoQUFETSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFBRE0sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBQURNX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0Encw0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFBRE0sIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBQURNIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCg0KREYkQUFETV9WRVJbaXMubmEoREYkQUFETV9WRVIpXSA8LSAwDQpERiRBQURNX1ZFUltERiRBQURNX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBQURNX1ZFUltERiRBQURNX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFBRE1baXMubmEoREYkQUFETSldIDwtIDANCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gQUxRVUlMRVIgREUgRVNQQUNJT1MgUFVCTElDSVRTQVJJT1MgKEFERVApDQoNCmBgYHtyfQ0KQURFUCA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIERFIEVTUEFDSU9TIFBVQkxJQ0lUU0FSSU9TIikNCkFERVAgPC0gZmlsdGVyKEFERVAsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQURFUCA8LSBzZWxlY3QoQURFUCwgLSdUaXBvIEluZ3Jlc28nKQ0KQURFUCA8LSBzZWxlY3QoQURFUCwgLSdSdWJybyBJbmdyZXNvJykNCkFERVAgPC0gc2VsZWN0KEFERVAsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBREVQLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQURFUF9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MNCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBREVQLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQURFUCIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQoNCkRGJEFERVBfVkVSW2lzLm5hKERGJEFERVBfVkVSKV0gPC0gMA0KREYkQURFUF9WRVJbREYkQURFUF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQURFUF9WRVJbREYkQURFUF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBREVQW2lzLm5hKERGJEFERVApXSA8LSAwDQojUmVlbXBsYXpvIGRlIE4vQSdzIHBvciAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIEFMUVVJTEVSIExPQ0FMRVMgQ09NRVJDSUFMRVMgKEFMQykNCg0KYGBge3J9DQpBTEMgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJBTFFVSUxFUiBMT0NBTEVTIENPTUVSQ0lBTEVTIikNCkFMQyA8LSBmaWx0ZXIoQUxDLEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCkFMQyA8LSBzZWxlY3QoQUxDLCAtJ1RpcG8gSW5ncmVzbycpDQpBTEMgPC0gc2VsZWN0KEFMQywgLSdSdWJybyBJbmdyZXNvJykNCkFMQyA8LSBzZWxlY3QoQUxDLCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgQUxDLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUxDX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBTEMsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBTEMiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KDQpERiRBTENfVkVSW2lzLm5hKERGJEFMQ19WRVIpXSA8LSAwDQpERiRBTENfVkVSW0RGJEFMQ19WRVIgIT0gMF0gPC0gIlNpIg0KREYkQUxDX1ZFUltERiRBTENfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkQUxDW2lzLm5hKERGJEFMQyldIDwtIDANCiNSZWVtcGxhem8gZGUgTi9BJ3MgcG9yIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gQUxRVUlMRVIgT0ZJQ0lOQVMgT1BFUkFDSU9ORVMgQUVST0zDjU5FQVMgKEFPT0EpDQoNCmBgYHtyfQ0KQU9PQSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFMUVVJTEVSIE9GSUNJTkFTIE9QRVJBQ0lPTkVTIEFFUk9Mw41ORUFTIikNCkFPT0EgPC0gZmlsdGVyKEFPT0EsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KQU9PQSA8LSBzZWxlY3QoQU9PQSwgLSdUaXBvIEluZ3Jlc28nKQ0KQU9PQSA8LSBzZWxlY3QoQU9PQSwgLSdSdWJybyBJbmdyZXNvJykNCkFPT0EgPC0gc2VsZWN0KEFPT0EsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBBT09BLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQU9PQV9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgQU9PQSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFPT0EiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkQU9PQV9WRVJbaXMubmEoREYkQU9PQV9WRVIpXSA8LSAwDQpERiRBT09BX1ZFUltERiRBT09BX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRBT09BX1ZFUltERiRBT09BX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJEFPT0FbaXMubmEoREYkQU9PQSldIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gQUxRVUlMRVJFUyBERSBBTE1BQ0VOL0hBTkdBUiAoQURBSCkNCg0KYGBge3J9DQpBREFIIDwtIGZpbHRlcihJVFMsIGBSdWJybyBJbmdyZXNvYCA9PSAiQUxRVUlMRVJFUyBERSBBTE1BQ0VOL0hBTkdBUiIpDQpBREFIIDwtIGZpbHRlcihBREFILEHDsW8gJWluJSBjKDIwMjAsMjAyMSwyMDIyKSkNCkFEQUggPC0gc2VsZWN0KEFEQUgsIC0nVGlwbyBJbmdyZXNvJykNCkFEQUggPC0gc2VsZWN0KEFEQUgsIC0nUnVicm8gSW5ncmVzbycpDQpBREFIIDwtIHNlbGVjdChBREFILCAtJ1BlcmlvZG8nKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgQURBSCwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIkFEQUhfVkVSIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KI0NyZWFjacOzbiBkZSB2YXJpYWJsZSBkZSB2ZXJpZmljYWNpw7NuIHBhcmEgcmVlbXBsYXpvIGRlIE4vQSdzIA0KYGBgDQoNCmBgYHtyfQ0KREYgPC0gbWVyZ2UoREYsIEFEQUgsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBREFIIiA9ICJJbXBvcnRlIHBvciBTZXJ2aWNpb3MiKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRX0NCkRGJEFEQUhfVkVSW2lzLm5hKERGJEFEQUhfVkVSKV0gPC0gMA0KREYkQURBSF9WRVJbREYkQURBSF9WRVIgIT0gMF0gPC0gIlNpIg0KREYkQURBSF9WRVJbREYkQURBSF9WRVIgPT0gIjAiXSA8LSAiTm8iDQpERiRBREFIW2lzLm5hKERGJEFEQUgpXSA8LSAwDQpgYGANCg0KIyMgVW5pZW5kbyBsYSB2YXJpYWJsZSBJbmdyZXNvIFJ1YnJvIEFURU5DScOTTiBFTiBIT1JBUyBFWFRSQVMgKEFFSEUpDQoNCmBgYHtyfQ0KQUVIRSA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIkFURU5DScOTTiBFTiBIT1JBUyBFWFRSQVMiKQ0KQUVIRSA8LSBmaWx0ZXIoQUVIRSxBw7FvICVpbiUgYygyMDIwLDIwMjEsMjAyMikpDQpBRUhFIDwtIHNlbGVjdChBRUhFLCAtJ1RpcG8gSW5ncmVzbycpDQpBRUhFIDwtIHNlbGVjdChBRUhFLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KQUVIRSA8LSBzZWxlY3QoQUVIRSwgLSdQZXJpb2RvJykNCmBgYA0KDQpgYGB7cn0NCg0KREYgPC0gbWVyZ2UoREYsIEFFSEUsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJBRUhFX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBBRUhFLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiQUVIRSIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUV9DQpERiRBRUhFX1ZFUltpcy5uYShERiRBRUhFX1ZFUildIDwtIDANCkRGJEFFSEVfVkVSW0RGJEFFSEVfVkVSICE9IDBdIDwtICJTaSINCkRGJEFFSEVfVkVSW0RGJEFFSEVfVkVSID09ICIwIl0gPC0gIk5vIg0KREYkQUVIRVtpcy5uYShERiRBRUhFKV0gPC0gMA0KYGBgDQoNCiMjIFVuaWVuZG8gbGEgdmFyaWFibGUgSW5ncmVzbyBSdWJybyBFU1RBQ0lPTkFNSUVOVE8gQUVST05BVkVTIChJUkVBKQ0KDQpgYGB7cn0NCklSRUEgPC0gZmlsdGVyKElUUywgYFJ1YnJvIEluZ3Jlc29gID09ICJFU1RBQ0lPTkFNSUVOVE8gQUVST05BVkVTIikNCklSRUEgPC0gZmlsdGVyKElSRUEsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJFQSA8LSBzZWxlY3QoSVJFQSwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJFQSA8LSBzZWxlY3QoSVJFQSwgLSdSdWJybyBJbmdyZXNvJykNCklSRUEgPC0gc2VsZWN0KElSRUEsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUkVBLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJFQV9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgSVJFQSwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSRUEiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJFQV9WRVJbaXMubmEoREYkSVJFQV9WRVIpXSA8LSAwDQpERiRJUkVBX1ZFUltERiRJUkVBX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRJUkVBX1ZFUltERiRJUkVBX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSRUFbaXMubmEoREYkSVJFQSldIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gSU5HUkVTT1MgRklOQU5DSUVST1MgKElSSUYpDQoNCmBgYHtyfQ0KSVJJRiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIklOR1JFU09TIEZJTkFOQ0lFUk9TIikNCklSSUYgPC0gZmlsdGVyKElSSUYsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJJRiA8LSBzZWxlY3QoSVJJRiwgLSdUaXBvIEluZ3Jlc28nKQ0KSVJJRiA8LSBzZWxlY3QoSVJJRiwgLSdSdWJybyBJbmdyZXNvJykNCklSSUYgPC0gc2VsZWN0KElSSUYsIC0nUGVyaW9kbycpDQpgYGANCg0KYGBge3J9DQoNCkRGIDwtIG1lcmdlKERGLCBJUklGLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJJRl9WRVIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQojQ3JlYWNpw7NuIGRlIHZhcmlhYmxlIGRlIHZlcmlmaWNhY2nDs24gcGFyYSByZWVtcGxhem8gZGUgTi9BJ3MgDQpgYGANCg0KYGBge3J9DQpERiA8LSBtZXJnZShERiwgSVJJRiwgYnkgPSBjKCJBw7FvIiwiTWVzIiwiQWVyb3B1ZXJ0byIsIkluZnJhZXN0cnVjdHVyYSIpLCBhbGw9VFJVRSkNCkRGIDwtIHJlbmFtZShERiwgIklSSUYiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJJRl9WRVJbaXMubmEoREYkSVJJRl9WRVIpXSA8LSAwDQpERiRJUklGX1ZFUltERiRJUklGX1ZFUiAhPSAwXSA8LSAiU2kiDQpERiRJUklGX1ZFUltERiRJUklGX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSSUZbaXMubmEoREYkSVJJRildIDwtIDANCmBgYA0KDQojIyBVbmllbmRvIGxhIHZhcmlhYmxlIEluZ3Jlc28gUnVicm8gUkVFTUJPTFNPUyAoSVJSKQ0KDQpgYGB7cn0NCklSUiA8LSBmaWx0ZXIoSVRTLCBgUnVicm8gSW5ncmVzb2AgPT0gIlJFRU1CT0xTT1MiKQ0KSVJSIDwtIGZpbHRlcihJUlIsQcOxbyAlaW4lIGMoMjAyMCwyMDIxLDIwMjIpKQ0KSVJSIDwtIHNlbGVjdChJUlIsIC0nVGlwbyBJbmdyZXNvJykNCklSUiA8LSBzZWxlY3QoSVJSLCAtJ1J1YnJvIEluZ3Jlc28nKQ0KSVJSIDwtIHNlbGVjdChJUlIsIC0nUGVyaW9kbycpDQoNCklSUiA8LSBmaWx0ZXIoSVJSLCBgSW1wb3J0ZSBwb3IgU2VydmljaW9zYCAhPSAwKQ0KYGBgDQoNCmBgYHtyfQ0KDQpERiA8LSBtZXJnZShERiwgSVJSLCBieSA9IGMoIkHDsW8iLCJNZXMiLCJBZXJvcHVlcnRvIiwiSW5mcmFlc3RydWN0dXJhIiksIGFsbD1UUlVFKQ0KREYgPC0gcmVuYW1lKERGLCAiSVJSX1ZFUiIgPSAiSW1wb3J0ZSBwb3IgU2VydmljaW9zIikNCiNDcmVhY2nDs24gZGUgdmFyaWFibGUgZGUgdmVyaWZpY2FjacOzbiBwYXJhIHJlZW1wbGF6byBkZSBOL0EncyANCmBgYA0KDQpgYGB7cn0NCkRGIDwtIG1lcmdlKERGLCBJUlIsIGJ5ID0gYygiQcOxbyIsIk1lcyIsIkFlcm9wdWVydG8iLCJJbmZyYWVzdHJ1Y3R1cmEiKSwgYWxsPVRSVUUpDQpERiA8LSByZW5hbWUoREYsICJJUlIiID0gIkltcG9ydGUgcG9yIFNlcnZpY2lvcyIpDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFfQ0KREYkSVJSX1ZFUltpcy5uYShERiRJUlJfVkVSKV0gPC0gMA0KREYkSVJSX1ZFUltERiRJUlJfVkVSICE9IDBdIDwtICJTaSINCkRGJElSUl9WRVJbREYkSVJSX1ZFUiA9PSAiMCJdIDwtICJObyINCkRGJElSUltpcy5uYShERiRJUlIpXSA8LSAwDQpgYGANCg0KIyMgQWdyZWdhbmRvIGxhIHZhcmlhYmxlIE51bWVybyBkZSBQYXNhamVyb3MgVG90YWxlcyAoTlApDQoNCmBgYHtyfQ0KREYgJT4lIG11dGF0ZShOUCA9IE5QTiArIE5QSSkgLT4gREYNCiNOdW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMNCmBgYA0KDQojIyBFbGltaW5hY2nDs24gZGUgZGF0b3MgeSBhcnJlZ2xvcw0KDQpgYGB7cn0NCiMgU2kgZXMgcXVlIG5vIHRlbmVtb3MgZWwgbm9tYnJlIGRlbCBhZXJvcHVlcnRvIG8gc3UgaW5mcmFlc3RydWN0dXJhIChTaWVtcHJlIGRlYmUgdmVuaXIgYWNvbXBhw7FhZGEgZGVsIG5vbWJyZSksIGxhIHVuaWRhZCBtdWVzdHJhbCBubyBwb2Ryw6EgZW50cmFyIGFsIGFuw6FsaXNpcyBwdWVzIHBvciBlamVtcGxvIHNpIG5vcyBkaWNlbiBjdWFudG8gZ2FubyB1biBhZXJvcHVlcnRvIGRlc2Nvbm9jaWRvLCBlc3RvIG5vIG5vcyBkaXLDoSBuYWRhLg0KDQoNCkRGJE1lcyA9IGZhY3RvcihERiRNZXMsIGxldmVscyA9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2V0aWVtYnJlIiwiT2N0dWJyZSIsIk5vdmllbWJyZSIsIkRpY2llbWJyZSIpKQ0KREYgPC0gYXJyYW5nZShERiwgQcOxbywgTWVzKQ0KDQpERiRBZXJvcHVlcnRvW0RGJEFlcm9wdWVydG8gPT0gJ05vIHByZWNpc2EnXSA8LSBOQQ0KREYkQWVyb3B1ZXJ0b1tERiRBZXJvcHVlcnRvID09ICctJ10gPC0gTkENCkRGJEluZnJhZXN0cnVjdHVyYVtERiRJbmZyYWVzdHJ1Y3R1cmEgPT0gJy0nXSA8LSBOQQ0KDQpERiA8LSBmaWx0ZXIoREYsIEluZnJhZXN0cnVjdHVyYSAhPSBpcy5uYSgiSW5mcmFlc3RydWN0dXJhIikgJiBBZXJvcHVlcnRvICE9IGlzLm5hKCJBZXJvcHVlcnRvIikpDQoNCkRGICU+JSBtdXRhdGUoIkVudGlkYWRfSW5mcmFlc3RydWN0dXJhIiA9DQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQURQIiwgIkFlcm9wdWVydG9zIGRlbCBQZXLDuiBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJBQVAiLCAiQWVyb3B1ZXJ0b3MgQW5kaW5vcyBkZWwgUGVyw7ogUy5BLiIsDQogICAgICAgICAgICAgICAgICBpZmVsc2UoSW5mcmFlc3RydWN0dXJhPT0iQ09SIiwgIkNPUlBBQyBTLkEuIiwNCiAgICAgICAgICAgICAgICAgIGlmZWxzZShJbmZyYWVzdHJ1Y3R1cmE9PSJMQVAiLCAiTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MLiIsSW5mcmFlc3RydWN0dXJhKSkpKSkgLT4gREYNCmBgYA0KDQpgYGB7cn0NCnN1bShjb21wbGV0ZS5jYXNlcyhERikpDQpgYGANCg0KYGBge3J9DQoNCkRGJE1lcyA9IGZhY3RvcihERiRNZXMsIGxldmVscyA9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2V0aWVtYnJlIiwiT2N0dWJyZSIsIk5vdmllbWJyZSIsIkRpY2llbWJyZSIpKQ0KREYgPC0gYXJyYW5nZShERiwgQcOxbywgTWVzKQ0KYGBgDQoNCiMjIEV4cG9ydGFuZG8gbGEgYmFzZSBkZSBkYXRvcw0KDQpgYGB7cn0NCndyaXRlX2NzdihERiwiQmFzZUxpbXBpYXYyLmNzdiIpDQoNCmBgYA0KDQojIEltcG9ydGFuZG8gbGEgYmFzZSBkYXRvcyBsaW1waWENCg0KYGBge3J9DQoNCnJtKGxpc3QgPSBscygpKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHBsb3RyaXgpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHN0cmluZ2kpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoTUFTUykNCg0KREYgPC0gcmVhZF9jc3YoIkJhc2VMaW1waWF2Mi5jc3YiKQ0KDQpgYGANCg0KIyBWYXJpYWJsZXMNCg0KKipBw7FvOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2EgZWwgYcOxbyBkZSBsYSByZWNvbGVjY2nDs24gZGUgaW5mb3JtYWNpw7NuLg0KDQoqKk1lczoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgaW5kaWNhIGVsIG1lcyBkZSBsYSByZWNvbGVjY2nDs24gZGUgaW5mb3JtYWNpw7NuLg0KDQoqKkFlcm9wdWVydG86KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBlbCBhZXJvcHVlcnRvIGRlbCBjdWFsIHNlIHJlY29sZWN0YSBsYSBpbmZvcm1hY2nDs24NCg0KKipJbmZyYWVzdHJ1Y3R1cmE6KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBlbiBhY3LDs25pbW8gYSBxdWUgZW50aWRhZCBwZXJ0ZW5lY2UgbGEgaW5mcmFlc3RydWN0dXJhIGRlbCBhZXJvcHVlcnRvIGRlbCBjdWFsIHNlIHJlY29sZWN0YSBsYSBpbmZvcm1hY2nDs24uDQoNCioqRW50aWRhZF9JbmZyYWVzdHJ1Y3R1cmE6KiogVmFyaWFibGUgY3VhbGl0YXRpdmEgcXVlIGluZGljYSBhIHF1ZSBlbnRpZGFkIHBlcnRlbmVjZSBsYSBpbmZyYWVzdHJ1Y3R1cmEgZGVsIGFlcm9wdWVydG8gZGVsIGN1YWwgc2UgcmVjb2xlY3RhIGxhIGluZm9ybWFjacOzbi4NCg0KKipJVDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqSVI6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGxvcyBpbmdyZXNvcyByZWd1bGFkb3MgZW4gZG9sYXJlcyBxdWUgaGEgcmVnaXN0cmFkbyBlbCBhZXJvcHVlcnRvDQoNCioqVFVVQU4qKjogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBxdWUgaGEgZ2VuZXJhZG8gbGEgKlRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPIGRlIHRpcG8gbmFjaW9uYWwuKg0KDQoqKlRVVUFOKio6IFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgcXVlIGhhIGdlbmVyYWRvIGxhICpUQVJJRkEgVU5JRklDQURBIFBPUiBVU08gREUgQUVST1BVRVJUTyBkZSB0aXBvIGludGVybmFjaW9uYWwuKg0KDQoqKk5QSToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0bw0KDQoqKk5QTjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBuYWNpb25hbGVzIHF1ZSBoYSByZWdpc3RyYWRvIGVsIGFlcm9wdWVydG8NCg0KKipJUkFEX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipJUkFEOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBpbmdyZXNvIGVuIGRvbGFyZXMgZGVsIGFlcm9wdWVydG8gcG9yIGF0ZXJyaXphamUgeSBkZXNwZWd1ZS4NCg0KKipBQURNX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIMOhcmVhcyBkZSBtYW50ZW5pbWllbnRvLg0KDQoqKkFBRE06KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgw6FyZWFzIGRlIG1hbnRlbmltaWVudG8uDQoNCioqQURFUF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBlc3BhY2lvcyBkZSBwdWJsaWNpZGFkLg0KDQoqKkFERVA6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgZXNwYWNpb3MgZGUgcHVibGljaWRhZC4NCg0KKipBTENfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBTEM6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgbG9jYWxlcyBjb21lcmNpYWxlcy4NCg0KKipBT09BX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGFscXVpbGVyIGRlIG9maWNpbmFzIGRlIG9wZXJhY2lvbmVzIGRlIGFlcm9sw61uZWFzLg0KDQoqKkFPT0E6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgZWwgYWxxdWlsZXIgZGUgb2ZpY2luYXMgZGUgb3BlcmFjaW9uZXMgZGUgYWVyb2zDrW5lYXMuDQoNCioqQURBSF9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQURBSDoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBhbHF1aWxlciBkZSBhbG1hY2VuZXMvaGFuZ2FyZXMuDQoNCioqQUVIRV9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciBsYSBhdGVuY2nDs24gZW4gaG9yYXMgZXh0cmFzLg0KDQoqKkFFSEU6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgbGEgYXRlbmNpw7NuIGVuIGhvcmFzIGV4dHJhcy4NCg0KKipJUkVBX1ZFUjoqKiBWYXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgcmVwcmVzZW50YSBzaSBlbCBhZXJvcHVlcnRvIG9idGllbmUgaW5ncmVzb3MgcG9yIGVsIGVzdGFjaW9uYW1pZW50byBkZSBhZXJvbmF2ZXMuDQoNCioqSVJFQToqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciBlbCBlc3RhY2lvbmFtaWVudG8gZGUgYWVyb25hdmVzLg0KDQoqKklSSUZfVkVSOioqIFZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSByZXByZXNlbnRhIHNpIGVsIGFlcm9wdWVydG8gb2J0aWVuZSBpbmdyZXNvcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSSUY6KiogVmFyaWFibGUgY3VhbnRpdGF0aXZhIHF1ZSByZXByZXNlbnRhIGVsIGluZ3Jlc28gZW4gZG9sYXJlcyBwb3IgcmVlbWJvbHNvIGVuIGluZ3Jlc29zIGZpbmFuY2llcm9zLg0KDQoqKklSUl9WRVI6KiogVmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIHJlcHJlc2VudGEgc2kgZWwgYWVyb3B1ZXJ0byBvYnRpZW5lIGluZ3Jlc29zIHBvciByZWVtYm9sc29zLg0KDQoqKklSUjoqKiBWYXJpYWJsZSBjdWFudGl0YXRpdmEgcXVlIHJlcHJlc2VudGEgZWwgaW5ncmVzbyBlbiBkb2xhcmVzIHBvciByZWVtYm9sc29zLg0KDQoqKk5QOioqIFZhcmlhYmxlIGN1YW50aXRhdGl2YSBxdWUgcmVwcmVzZW50YSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGhhIHJlZ2lzdHJhZG8gZWwgYWVyb3B1ZXJ0by4NCg0KIyBEZXNjcmlwdG9yZXMgTnVtw6lyaWNvcw0KDQpgYGB7cn0NCmN2IDwtIGZ1bmN0aW9uKHgpew0KICAgIHJldHVybihzZCh4LCBuYS5ybT1UKS9tZWFuKHgsIG5hLnJtPVQpKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KdGFibGEgPC0gZGF0YS5mcmFtZShWYXJpYWJsZXMgPSBjKCdJVCcsICdOUE4nLCAnTlBJJywgJ1RVVUFOJywnVFVVQUknKSwNCiAgICAgICAgICAgICAgICAgICAgTWVkaWEgPSBjKG1lYW4oREYkSVQsIG5hLnJtPVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFOLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuKERGJFRVVUFJLCBuYS5ybT0gVCkpLA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgTWVkaWFuYSA9IGMobWVkaWFuKERGJElULCBuYS5ybT1UKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYW4oREYkTlBJLCBuYS5ybT0gVCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBTiwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihERiRUVVVBSSwgbmEucm09IFQpKSwgDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBEZXN2aWFjaW9uID0gYyhzZChERiRJVCwgbmEucm09VCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUE4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZChERiROUEksIG5hLnJtPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QoREYkVFVVQUksIG5hLnJtPSBUKSksIA0KICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgVmFyaWFuemEgPSBjKHZhcihERiRJVCwgbmEucm0gPSBUKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiROUEksIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyKERGJFRVVUFOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBSYW5nb0ludGVyY3VhcnRpbCA9IGMoSVFSKERGJElULCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBOLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkTlBJLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJUVIoREYkVFVVQU4sIG5hLnJtID0gVCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElRUihERiRUVVVBSSwgbmEucm0gPSBUKSksDQogICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICBDb2VmaWNpZW50ZVZhcmlhY2lvbiA9IGMoY3YoREYkSVQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN2KERGJE5QTiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3YoREYkTlBJKSkpDQp0YWJsYQ0KYGBgDQoNCkRlIGxhIHRhYmxhIHBvZGVtb3MgY29uc2VndWlyIGxhIHNpZ3VpZW50ZSBpbmZvcm1hY2nDs246DQoNCi0gICBMYSBlc2NhbGEgY29uIGxhIHF1ZSBzZSB0cmFiYWphIGVzIGJhc3RhbnRlIGdyYW5kZSwgZGUgYWjDrSBlbCBoZWNobyBxdWUgbGEgdmFyaWFuemEgeSBkZXN2aWFjacOzbiBzZWFuIHRhbiBncmFuZGUuDQoNCi0gICBUYW50byBsYSB2YXJpYW56YSBjb21vIGxhIGRlc3ZpYWNpw7NuIG5vcyBpbmRpY2FuIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIEluZ3Jlc29zIFRvdGFsZXMsIGVsIE51bWVybyBkZSBQYXNhamVyb3MgTmFjaW9uYWxlcyB5IGVsIE51bWVybyBkZSBQYXNhamVyb3MgSW50ZXJuYWNpb25hbGVzIGVzdMOhbiBtdXkgZGlzcGVyc29zLg0KDQotICAgU2UgYXByZWNpYSB1biBmZW7Ds21lbm8gcXVlIGxhIG1lZGlhbmEgeSBlbCByYW5nbyBpbnRlcmN1YXJ0aWwgZGUgbGEgdmFyaWFibGUgUGFzYWplcm9zIGludGVybmFjaW9uYWxlcyBlcyAwLiBFc3RvIHF1aWVyZSBkZWNpciBxdWUgaGF5IG11Y2hvcyBhZXJvcHVlcnRvcyBsb3MgY3VhbGVzIG5vIHN1ZWxlbiByZWNpYmlyIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMuDQoNCiMgRGVzY3JpcHRvcmVzIEdyw6FmaWNvcw0KDQojIyBOdW1lcm8gZGUgUGFzYWplcm9zIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQoNCmBgYA0KDQpDb21lbnphbW9zIGNvbXBhcmFuZG8gZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB0b3RhbGVzLCBzdW1hIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgeSBuYWNpb25hbGVzLCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGUgY2FkYSBhZXJvcHVlcnRvIGVuIGRldGVybWluYWRvIG1lcyB5IGHDsW8gZW4gbWlsbG9uZXMgZGUgZG9sYXJlcy4gQSBzaW1wbGUgdmlzdGEgc2UgcHVlZGUgdmVyIHVuIGNpZXJ0byB0aXBvIGRlIHJlbGFjacOzbiBsaW5lYWwsIHNpbiBlbWJhcmdvIHRlbmVtb3MgcXVlIGNvbXByb2JhcmxvLiBVc2FyZW1vcyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24geWEgcXVlIGVzdGUgbm8gdG9tYSBlbiBjdWVudGEgbGEgZXNjYWxhIGRlIGxhcyB1bmlkYWRlcywgcGVyZmVjdG8gcGFyYSBudWVzdHJvIGVzdHVkaW8uDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiROUCwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkNvbiBsYSBpbmZvcm1hY2nDs24gc3VtaW5pc3RyYWRhIGRlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gc2UgZGVkdWNlIHF1ZSBsYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGVsIG51bWVybyBkZSBwYXNhamVyb3MgeSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlcyBidWVuYSwgY2FzaSBwZXJmZWN0YSB5IGFzY2VuZGVudGUuIEVzIGRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGF1bWVudGFyYW4gZW4gY3VhbnRvIGF1bWVudGUgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcy4NCg0KQWhvcmEgY3JlYXJlbW9zIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3J9DQoNCm1vZGVsbyA9IGxtKERGJElUIH4gREYkTlAsIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUC8xMDAwLCAiWSI9REYkSVQvMTAwMDAwMCkNCm1vZGVsbyA9IGxtKGQkWSB+IGQkWCwgZGF0YT1kKQ0KbW9kZWxvDQpgYGANCg0KSGVtb3MgY3JlYWRvIGRvcyBtb2RlbG9zIHF1ZSBlbiByZWFsaWRhZCBzb24gZWwgbWlzbW8gcGVybyBhIGRpZmVyZW50ZXMgZXNjYWxhcy4gRWwgcHJpbWVybyBub3Mgc2lydmUgcGFyYSB1c2FyIGRpcmVjdGFtZW50ZSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIHkgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZW4gZG9sYXJlcy4gRWwgc2VndW5kbyBwYXJhIHVzYXIgZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB5IGNvbnNlZ3VpciBsb3MgaW5ncmVzb3MgdG90YWxlcyBlbiBtaWxsb25lcyBkZSBkb2xhcmVzLiBBbWJvcyBtb2RlbG9zIG5vcyBwZXJtaXRlbiBhcHJveGltYXIsIHByZWRlY2lyIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIHVuIGFlcm9wdWVydG8gZW4gZGV0ZXJtaW5hZG8gbWVzIHkgYcOxbyB1c2FuZG8gbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIHRvdGFsZXMgcXVlIGxsZXZvIGVuIGVsIG1pc21vIGxhcHNvIGRlIHRpZW1wby4NCg0KYGBge3J9DQpwbG90KERGJE5QLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJkYXJrZ3JlZW4iLCBwY2g9IuKAoiIsIHhsaW0gPSBjKDAsMjAwMCkpDQphYmxpbmUoYT0gLTAuMTQ4OTAsIGI9MC4wMTY0NiwgY29sPSJncmVlbiIpDQpgYGANCg0KIyMgTnVtZXJvIGRlIFBhc2FqZXJvcyBOYWNpb25hbGVzIGUgSW50ZXJuYWNpb25hbGVzIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KDQpwbG90KERGJE5QTi8xMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIk51bWVybyBkZSBwYXNhamVyb3MgbmFjaW9uYWxlcyAobWlsZXMpIiwgeWxhYiA9ICJJbmdyZXNvcyB0b3RhbGVzIChtaWxsb25lcyBkZSBVUyQpIiwgY29sPSJyZWQiLCBwY2g9IuKAoiIpDQoNCnBsb3QoREYkTlBJLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iYmx1ZSIsIHBjaD0i4oCiIikNCmBgYA0KDQpBaG9yYSB2YW1vcyBhIGFuYWxpemFyIGxhIHJlbGFjacOzbiBkZSBsb3MgdGlwb3MgZGUgcGFzYWplcm9zIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcy4gRGUgbnVldm8gdXNhcmVtb3MgZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHRhbnRvIHBhcmEgbG9zIHBhc2FqZXJvcyBuYWNpb25hbGVzIGNvbW8gaW50ZXJuYWNpb25hbGVzLg0KDQpgYGB7cn0NCmNvcihERiRJVCwgREYkTlBOLCB1c2U9ImNvbXBsZXRlLm9icyIpDQpjb3IoREYkSVQsIERGJE5QSSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkRlIGxvcyBjb2VmaWNpZW50ZXMgZGFkb3Mgc2UgZW5jdWVudHJhIHF1ZToNCg0KLSAgIEFtYm9zIGRlbXVlc3RyYW4gcXVlIHRhbnRvIGxvcyBwYXNhamVyb3MgbmFjaW9uYWxlcyBjb21vIGludGVybmFjaW9uYWxlcyBwb3NlZW4gdW5hIGJ1ZW5hIHkgYXNjZW5kZW50ZSByZWxhY2nDs24gbGluZWFsIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcy4NCi0gICBBbWJvcyBzb24gbWVub3JlcyBhbCAqKmNvcioqIGRlIGxvcyBwYXNhamVyb3MgdG90YWxlcyBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMuIEluZGljYSBxdWUgc2kgc2UgdXNhIHNvbG8gYSBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMgbyBzb2xvIGEgbG9zIGludGVybmFjaW9uYWxlcyBwYXJhIGFwcm94aW1hciBsb3MgaW5ncmVzb3MgdG90YWxlcywgc2UgdGVuZHLDoSB1bmEgcHJlY2lzacOzbiBtZW5vciBhIHF1ZSBzaSBzZSB1c2Fyw6EgbGEgc3VtYSBkZSBhbWJvcy4NCi0gICBFbCAqKmNvcioqIGRlIGxvcyBwYXNhamVyb3MgaW50ZXJuYWNpb25hbGVzIGVzIGxpZ2VyYW1lbnRlIHN1cGVyaW9yIGFsIGRlIGxvcyBwYXNhamVyb3MgbmFjaW9uYWxlcywgbW9zdHJhbmRvIHF1ZSBzdSByZWxhY2nDs24gbGluZWFsIGNvbiBsb3MgaW5ncmVzb3MgdG90YWxlcyBlcyBsaWdlcmFtZW50ZSBtw6FzIGFjb3JkZSBxdWUgbGEgcmVsYWNpw7NuIGxpbmVhbCBkZSBsb3MgcGFzYWplcm9zIG5hY2lvbmFsZXMuDQoNCkFob3JhIGNvbnN0cnV5YW1vcyBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCBwYXJhIGNhZGEgdW5vLg0KDQpgYGB7cn0NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiROUE4sIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj1ERiROUE4vMTAwMCwgIlkiPURGJElULzEwMDAwMDApDQptb2RlbG8gPSBsbShkJFkgfiBkJFgsIGRhdGE9ZCkNCm1vZGVsbw0KDQptb2RlbG8gPSBsbShERiRJVCB+IERGJE5QSSwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJE5QSS8xMDAwLCAiWSI9REYkSVQvMTAwMDAwMCkNCm1vZGVsbyA9IGxtKGQkWSB+IGQkWCwgZGF0YT1kKQ0KbW9kZWxvDQoNCnJtKGQpDQpgYGANCg0KVmVtb3MgcXVlIGxvcyBtb2RlbG9zIGRpZmllcmVuIGVuIHVuYSBjYW50aWRhZCBjb25zaWRlcmFibGUgZW4gY3VhbnRvIGEgc3UgcGVuZGllbnRlLCBzaW4gZW1iYXJnbywgc3UgaW50ZXJjZXB0byBlcyBiYXN0YW50ZSBzaW1pbGFyLCB2YW1vcyBhIGdyYWZpY2FyIGVzdG9zIG1vZGVsb3MuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCg0KcGxvdChERiROUE4vMTAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJOdW1lcm8gZGUgcGFzYWplcm9zIG5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0icmVkIiwgcGNoPSLigKIiKQ0KYWJsaW5lKGE9IC0wLjM2MDMzLCBiPTAuMDI0NTEsIGNvbD0iI2Y3MjU4NSIpDQoNCnBsb3QoREYkTlBJLzEwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiTnVtZXJvIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgKG1pbGVzKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iYmx1ZSIsIHBjaD0i4oCiIikNCmFibGluZShhPSAwLjMxOTk2LCBiPTAuMDQ3NzIsIGNvbD0iIzAwNzdiNiIpDQpgYGANCg0KIyMgQW5hbGl6YW5kbyBsYSBkaXN0cmlidWNpw7NuIGRlIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwbG90X2x5KHggPSB+REYkSVQvMTAwMDAwMCwNCiAgICAgICAgdHlwZT0iaGlzdG9ncmFtIiwNCiAgICAgICAgY29sb3IgPSB+REYkSW5mcmFlc3RydWN0dXJhLA0KICAgICAgICBuYmluc3ggPSAxMDANCiAgICAgICAgKSU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiRnJlY3VlbmNpYSIgKSwNCiAgICB4YXhpcyA9IGxpc3QoIHRpdGxlID0gIkluZ3Jlc29zIHRvdGFsZXMgKE1pbGxvbmVzIGRlIFVTJCkiLA0KICAgICAgICAgICAgICAgICAgbnRpY2tzID0gMjApKQ0KYGBgDQoNCkdyYWNpYXMgYWwgaGlzdG9ncmFtYSBzZSBkaWNlIHF1ZSBsb3MgZGF0b3MgZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgc29uIHRvdGFsbWVudGUgYXNpbcOpdHJpY29zIHkgc2UgZW5jdWVudHJhbiBhY3VtdWxhZG9zIGVuIHVuIGludGVydmFsbyBkZSAwIC0gMC41IG1pbGxvbmVzIGRlIGRvbGFyZXMuIEVzIGRlY2lyIGxhIG1heW9yw61hIGRlIGFlcm9wdWVydG9zIGRldGVybWluYWRvcyBlbiBjaWVydG8gbWVzIHkgY2llcnRvIGHDsW8gcG9zZWUgdW5vcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGVudHJlIDAgeSAwLjUgbWlsbG9uZXMgZGUgZG9sYXJlcy4gRXN0byBwdWVkZSBvY3VycmlyIGRlYmlkbyBhIGRhdG9zIGF0w61waWNvcywgY29uc3RydXlhbW9zIHVuIEJveHBsb3QgcGFyYSBxdWUgbm9zIGF5dWRlLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHg9fkRGJElULzEwMDAwMDAsDQogICAgICAgICAgICB0eXBlID0gImJveCIpJT4lDQpsYXlvdXQoDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KVXNhbmRvIHVuIEJveHBsb3Qgc2ltcGxlIHNlIGNvbXBydWViYSBjb21vIGxvcyBkYXRvcyBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyBlc3TDoW4gZGVtYXNpZG9zIGRpc3BlcnNvcyBncmFjaWFzIGEgY2llcnRhIGNhbnRpZGFkIGRlIGRhdG9zIGF0aXBpY29zLiBBaG9yYSBlcyBuZWNlc2FyaW8gYXZlcmlndWFyIGRlIGRvbmRlIHByb3ZpZW5lbiBlc3RvcyBkYXRvcyBhdMOtcGljb3MgeSBxdWUgbm9zIHF1aWVyZW4gZGVjaXIuIFBhcmEgZWxsbyBjcmVhcmVtb3MgZGlmZXJlbnRlcyBCb3hwbG90cyBiYXNhZG9zIGVuIG1lc2VzLCBpbmZyYWVzdHJ1Y3R1cmFzIHkgYWVyb3B1ZXJ0b3MuDQoNCmBgYHtyfQ0KcGxvdF9seShERiwgeCA9IH5JVC8xMDAwMDAwLCANCiAgICAgICAgeSA9IH5NZXMsIA0KICAgICAgICBjb2xvcj0gfk1lcywgDQogICAgICAgIHR5cGU9ImJveCIpICU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiTWVzIiksDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KQ29uIGVzdGUgZ3LDoWZpY28gcG9kZW1vcyBkZXNjYXJ0YXIgcXVlIGxvcyBkYXRvcyBhdMOtcGljb3MgcHJvdmVuZ2FuIGRlIHVuIG8gdmFyaW9zIG1lc2VzIGVuIGVzcGVjw61maWNvLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYsIHggPSB+SVQvMTAwMDAwMCwgDQogICAgICAgIHkgPSB+SW5mcmFlc3RydWN0dXJhLCANCiAgICAgICAgY29sb3I9IH5FbnRpZGFkX0luZnJhZXN0cnVjdHVyYSwgDQogICAgICAgIHR5cGU9ImJveCIpICU+JQ0KbGF5b3V0KHlheGlzID0gbGlzdCggdGl0bGUgPSAiSW5mcmFlc3RydWN0dXJhIiksDQogICAgeGF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIikpDQpgYGANCg0KRW4gZXN0ZSBncsOhZmljbyBzZSBvYnNlcnZhIGNvbW8gTGltYSBBaXJwb3J0IFBhcnRuZXJzIFMuUi5MIHJlYmFzYSBwb3IgbXVjaG8gYSBsYXMgb3RyYXMgaW5mcmFlc3RydWN0dXJhcyBlbiBjdWFudG8gYSBpbmdyZXNvcyB0b3RhbGVzIHNlIHJlZmllcmUuIEFxdcOtIHBvZGVtb3MgeWEgc2FiZXIgcXVlIGVzb3MgZGF0b3MgYXTDrXBpY29zIGRlIGluZ3Jlc29zIGVzdMOhbiBnZW5lcmFkb3MgZW4gc3UgZ3JhbiBtYXlvcsOtYSBwb3IgbGEgaW5mcmFlc3RydWN0dXJhIExpbWEgQWlycG9ydCBQYXJ0bmVycyBTLlIuTC4gQWRlbcOhcyBlcyBpbXBvcnRhbnRlIG1lbmNpb25hciBxdWUgbGEgaW5mcmFlc3RydWN0dXJhIENPUiBubyBhcGFyZWNlIGVuIGxhIGdyw6FmaWNhIHB1ZXMgbm8gaGEgZGVjbGFyYWRvIG5pbmfDum4gaW5ncmVzbyB0b3RhbC4NCg0KYGBge3J9DQpwbG90X2x5KERGLCB4ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB5ID0gfkFlcm9wdWVydG8sIA0KICAgICAgICBjb2xvcj0gfkFlcm9wdWVydG8sIA0KICAgICAgICB0eXBlPSJib3giDQogICAgICAgICkgJT4lDQpsYXlvdXQoeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJBZXJvcHVlcnRvcyIpLA0KICAgIHhheGlzID0gbGlzdCggdGl0bGUgPSAiSW5ncmVzb3MgdG90YWxlcyAoTWlsbG9uZXMgZGUgVVMkKSIpKQ0KYGBgDQoNCkdyYWNpYXMgYSBsb3MgMyBncsOhZmljb3MgcG9kZW1vcyBjb25jbHVpciBxdWU6DQoNCi0gICBFbCBhZXJvcHVlcnRvIGRlIExpbWEgY3V5YSBlbnRpZGFkIHByZXN0YWRvcmEgZXMgbGEgTEFQLCBlcyBsYSByZXNwb25zYWJsZSBkZSBsb3MgZGF0b3MgYXTDrXBpY29zIHkgYWRlbcOhcyBlcyBlbCBxdWUgbcOhcyBpbmdyZXNvcyB0b3RhbGVzIGdlbmVyYS4NCi0gICBMYSBpbmZyYWVzdHJ1Y3R1cmEgTEFQIHRyYWJhamEgZW4gTGltYSB5IHNlIHJlZmllcmUgYWwgQWVyb3B1ZXJ0byBJbnRlcm5hY2lvbmFsIEpvcmdlIENow6F2ZXouIEVzdG8gbm9zIHF1aWVyZSBkZWNpciBxdWUgZW4gZWwgUGVyw7osIGVsIGFlcm9wdWVydG8gcXVlIGdlbmVyYSBtw6FzIGluZ3Jlc29zIGVzIGVsIEpvcmdlIENow6F2ZXouDQoNCiMjIE51bWVybyBkZSBQYXNhamVyb3MgdnMgQWVyb3B1ZXJ0b3MNCg0KYGBge3J9DQpwbG90X2x5KERGLHkgPSB+TlAvMTAwMCwNCiAgICAgICAgeCA9IH5hcy5mYWN0b3IoQWVyb3B1ZXJ0byksIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yPWMoImxpZ2h0Ymx1ZSIpKQ0KICAgICAgICApJT4lDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiQWVyb3B1ZXJ0b3MiKSwNCiAgICB5YXhpcyA9IGxpc3QoIHRpdGxlID0gIk51bWVybyBkZSBwYXNhamVyb3MgKG1pbGVzKSIpKQ0KYGBgDQoNCkNvbiBlc3RhIGdyw6FmaWNvIHNlIGNvcnJvYm9yYSBxdWUgZWwgQWVyb3B1ZXJ0byBkZSBMaW1hIChBZXJvcHVlcnRvIEludGVybmFjaW9uYWwgSm9yZ2UgQ2jDoXZleikgZ2VuZXJhIGxhIG1heW9yIGNhbnRpZGFkIGRlIGluZ3Jlc29zIHkgYWRlbcOhcyByZWNpYmUgYSBsYSBtYXlvciBjYW50aWRhZCBkZSBwYXNhamVyb3MgcmVzcGVjdG8gYWwgcmVzdG8gZGVsIFBlcsO6LiBPdHJvcyBhZXJvcHVlcnRvcyBub3RhYmxlcyBzb24gQ3VzY28sIEFyZXF1aXBhIGUgSXF1aXRvcyBkb25kZSBDdXNjbyBlcyBlbCBxdWUgbcOhcyBwYXNhamVyb3MgcmVjaWJlIGZ1ZXJhIGRlIExpbWEuIFNlIHByb2NlZGUgYSBkaWJ1amFyIGVsIG51bWVybyBkZSBwYXNhamVyb3MsIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHkgbG9zIGFlcm9wdWVydG9zLg0KDQpgYGB7cn0NCnBsb3RfbHkoREYseCA9IH5OUC8xMDAwLA0KICAgICAgICB5ID0gfklULzEwMDAwMDAsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgY29sb3IgPSB+YXMuZmFjdG9yKEFlcm9wdWVydG8pDQogICAgICAgICkNCmBgYA0KDQpFbCBncsOhZmljbyBub3MgZGVqYSBlbiBjbGFybyBsYSBlc3RyZWNoYSByZWxhY2nDs24gZGUgbGEgY2FudGlkYWQgZGUgcGFzYWplcm9zIGNvbiBsYSBkZSBpbmdyZXNvcyBxdWUgcG9zZWUgZWwgYWVyb3B1ZXJ0byBkZSBMaW1hIHkgY29tbyBlc3RlIHNvYnJlc2FsZSBwb3IgbXVjaG8gZGVsIHJlc3RvIGRlIGFlcm9wdWVydG9zLiBTZSBjb25jbHV5ZSBxdWUgbG9zIGRhdG9zIGF0w61waWNvcyBwcm92ZW5pZW50ZXMgZGUgaW5ncmVzb3MgdG90YWxlcyBlcmFuIHkgbm9zIGNvbnRhYmFuIHNvYnJlIGxhcyBwZWN1bGlhcmlkYWRlcyBkZWwgY2FzbyBMaW1hLg0KDQojIyBJbmdyZXNvcyBUIFUgVSBBIFRvdGFsIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KU2UgZWxpZ2nDsyBsYSBjb21wYXJhY2nDs24gZGUgbGFzIFQgVSBVIEEsIHBvcnF1ZSBlc3RhIGVzIGxhIFRBUklGQSBVTklGSUNBREEgUE9SIFVTTyBERSBBRVJPUFVFUlRPLCBlcyBkZWNpciBlcyB1bmEgdGFyaWZhIHF1ZSBjb21vIGNvbnN1bWlkb3JlcyBkZWJlbW9zIGRlIHBhZ2FyLiBFbCBvYmpldGl2byBhcXXDrSBlcyBhbmFsaXphciBjdWFudG8gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgcHJvdmllbmVuIGRpcmVjdGFtZW50ZSBkZSBsb3MgYm9sc2lsbG9zIGRlIGxvcyBwYXNhamVyb3MuDQoNCmBgYHtyfQ0KcGxvdCgoREYkVFVVQU4vMTAwMDAwMCArIERGJFRVVUFJLzEwMDAwMDApLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MjZjMTUiLCBwY2g9IuKAoiIpDQoNCmBgYA0KDQpDb21lbnphbW9zIGNvbXBhcmFuZG8gZWwgbnVtZXJvIGRlIHBhc2FqZXJvcyBlbiBtaWxlcyB0b3RhbGVzLCBzdW1hIGRlIHBhc2FqZXJvcyBpbnRlcm5hY2lvbmFsZXMgeSBuYWNpb25hbGVzLCBjb24gbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGUgY2FkYSBhZXJvcHVlcnRvIGVuIGRldGVybWluYWRvIG1lcyB5IGHDsW8gZW4gbWlsbG9uZXMgZGUgZG9sYXJlcy4gQSBzaW1wbGUgdmlzdGEgc2UgcHVlZGUgdmVyIHVuIGNpZXJ0byB0aXBvIGRlIHJlbGFjacOzbiBsaW5lYWwsIHNpbiBlbWJhcmdvIHRlbmVtb3MgcXVlIGNvbXByb2JhcmxvLiBVc2FyZW1vcyBlbCBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24geWEgcXVlIGVzdGUgbm8gdG9tYSBlbiBjdWVudGEgbGEgZXNjYWxhIGRlIGxhcyB1bmlkYWRlcywgcGVyZmVjdG8gcGFyYSBudWVzdHJvIGVzdHVkaW8uDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiRUVVVBSSArIERGJFRVVUFOLCB1c2U9ImNvbXBsZXRlLm9icyIpDQpgYGANCg0KVGVuZW1vcyB1biBjb2VmaWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gcXVlIGVzdGEgbXV5IHByw7N4aW1vIGEgMSwgZXMgZGVjaXIgZXN0YSByZWxhY2nDs24gZXMgY2FzaSBwZXJmZWN0YW1lbnRlIGxpbmVhbCB5IGNvbiB0ZW5kZW5jaWEgYXNjZW5kZW50ZS4NCg0KQWhvcmEgY3JlYXJlbW9zIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4NCg0KYGBge3J9DQpUVVVBIDwtIERGJFRVVUFJK0RGJFRVVUFODQptb2RlbG8gPSBsbShERiRJVCB+IFRVVUEsIGRhdGE9REYpDQptb2RlbG8NCg0KZCA8LSBkYXRhLmZyYW1lKCJYIj0gKERGJFRVVUFJICsgREYkVFVVQU4pLzEwMDAwMCwgIlkiPURGJElULzEwMDAwMDApDQptb2RlbG8gPSBsbShkJFkgfiBkJFgsIGRhdGE9ZCkNCm1vZGVsbw0KDQpybShkKQ0KYGBgDQoNCkRlbCBtb2RlbG8gY3JlYWRvIHNlIG9idGllbmUgZWwgaW50ZXJjZXB0bywgZXMgZGVjaXIgY3VhbmRvIGxhIFRVVUEgdmFsZHLDoSBjZXJvIHkgbGEgcGVuZGllbnRlLCBlbiBlc3RlIGNhc28gZXMgcmVsYXRpdmFtZW50ZSBiYWphIHBlcm8gYXNjZW5kZW50ZS4NCg0KYGBge3J9DQpwbG90KFRVVUEvMTAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgdG90YWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MjZjMTUiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gMC4xNTU3LCBiPTAuMjE5MCwgY29sPSIjYzlhMjI3IikNCmBgYA0KDQojIyBJbmdyZXNvcyBUVVVBIE5hY2lvbmFsIHkgVFVVQSBJbnRlcm5hY2lvbmFsIHZzIEluZ3Jlc29zIFRvdGFsZXMNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KDQpwbG90KERGJFRVVUFOLzEwMDAwMDAsIERGJElULzEwMDAwMDAsIHhsYWIgPSAiSW5ncmVzb3MgVFVVQSBuYWNpb25hbCAobWlsbG9uZXMgZGUgVVMkKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iI2Y4OTYxZSIsIHBjaD0i4oCiIikNCg0KcGxvdChERiRUVVVBSS8xMDAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgaW50ZXJuYWNpb25hbCAobWlsbG9uZXMgZGUgVVMkKSIsIHlsYWIgPSAiSW5ncmVzb3MgdG90YWxlcyAobWlsbG9uZXMgZGUgVVMkKSIsIGNvbD0iIzkwYmU2ZCIsIHBjaD0i4oCiIikNCmBgYA0KDQpQcm9iZW1vcyBkZSBudWV2byBhIHVzYXIgZWwgY29lZmljaWVudGUgZGUgY29ycmVsYWNpw7NuIHBhcmEgYW1iYXMgdmFyaWFibGVzDQoNCmBgYHtyfQ0KY29yKERGJElULCBERiRUVVVBTiwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KY29yKERGJElULCBERiRUVVVBSSwgdXNlPSJjb21wbGV0ZS5vYnMiKQ0KYGBgDQoNCkRlIGxvcyBjb2VmaWNpZW50ZXMgZGFkb3Mgc2UgZW5jdWVudHJhIHF1ZToNCg0KLSAgIExvcyBkb3MgY29lZmljaWVudGVzIG11ZXN0cmFuIHVuYSBjYXNpIHBlcmZlY3RhIGxpbmVhbGlkYWQgYXNjZW5kZW50ZS4NCi0gICBOaW5ndW5vIGRlIGxvcyBkb3MgKipjb3IqKiBwb3Igc2VwYXJhZG8gcHVkbyBzdXBlcmFyIGFsIGFudGVyaW9yIHZpc3RvIHByb2R1Y3RvIGRlIGxhIHN1bWEgZGUgbGFzIFRVVUEuDQotICAgRWwgKipjb3IqKiBuYWNpb25hbCBlcyBsaWdlcmFtZW50ZSBzdXBlcmlvciBhbCAqKmNvcioqIGludGVybmFjaW9uYWwuDQoNCkFob3JhIGNvbnN0cnV5YW1vcyBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuIGxpbmVhbCBwYXJhIGNhZGEgdW5vLg0KDQpgYGB7cn0NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiRUVVVBTiwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJFRVVUFOLzEwMDAwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0KbW9kZWxvID0gbG0oREYkSVQgfiBERiRUVVVBSSwgZGF0YT1ERikNCm1vZGVsbw0KDQpkIDwtIGRhdGEuZnJhbWUoIlgiPURGJFRVVUFJLzEwMDAwMDAsICJZIj1ERiRJVC8xMDAwMDAwKQ0KbW9kZWxvID0gbG0oZCRZIH4gZCRYLCBkYXRhPWQpDQptb2RlbG8NCg0Kcm0oZCkNCmBgYA0KDQpMb3MgbW9kZWxvcyBwb3NlZW4gYmFzdGFudGVzIGRpZmVyZW5jaWFzIGVudHJlIHPDrSBjb21vIHN1cyBpbnRlcmNlcHRvcyBxdWUgYSBzaW1wbGUgbm8gdGllbmVuIG5hZGEgZW4gY29tw7puIGFsIGlndWFsIHF1ZSBzdXMgcGVuZGllbnRlcy4gVmVhbW9zbG8gZW4gdW5hIGdyYWZpY2EuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCg0KcGxvdChERiRUVVVBTi8xMDAwMDAwLCBERiRJVC8xMDAwMDAwLCB4bGFiID0gIkluZ3Jlc29zIFRVVUEgbmFjaW9uYWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiNmODk2MWUiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gLTAuMDU5OSwgYj01LjIxMjYsIGNvbD0iI2YzNzIyYyIpDQoNCnBsb3QoREYkVFVVQUkvMTAwMDAwMCwgREYkSVQvMTAwMDAwMCwgeGxhYiA9ICJJbmdyZXNvcyBUVVVBIGludGVybmFjaW9uYWwgKG1pbGxvbmVzIGRlIFVTJCkiLCB5bGFiID0gIkluZ3Jlc29zIHRvdGFsZXMgKG1pbGxvbmVzIGRlIFVTJCkiLCBjb2w9IiM5MGJlNmQiLCBwY2g9IuKAoiIpDQphYmxpbmUoYT0gMC4zMjk1LCBiPTMuNjg4MiwgY29sPSIjNDNhYThiIikNCg0KYGBgDQoNCkRldGFsbGFtb3MgZW50b25jZXMgcXVlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGd1YXJkYW4gdW5hIGFsdGEgcmVsYWNpw7NuIGNvbiBsb3MgaW5ncmVzb3MgZ2VuZXJhZG9zIHBvciBsYXMgVFVVQSB5IGRlcGVuZGVuIGVuIGdyYW4gbWVkaWRhIGRlIGVzdGFzLCBlcmdvIGxhIGNhbnRpZGFkIGRlIHBhc2FqZXJvcy4NCg0KIyMgUGFuZGVtaWEgdnMgUG9zdFBhbmRlbWlhDQoNCmBgYHtyfQ0KREYyMDIwIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjAiKQ0KREYyMDIxIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjEiKQ0KREYyMDIyIDwtIGZpbHRlcihERiwgREYkQcOxbz09IjIwMjIiKQ0KDQpERjIwMjAgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMA0KDQpERjIwMjEgJT4lIGdyb3VwX2J5KE1lcyxBw7FvKSAlPiUgc3VtbWFyaXNlKElUID0gc3VtKElULCBuYS5ybT1UUlVFKSwgTlAgPSBzdW0oTlAsIG5hLnJtID0gVFJVRSkpIC0+IERGMjAyMQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KREYyMDIyICU+JSBncm91cF9ieShNZXMsQcOxbykgJT4lIHN1bW1hcmlzZShJVCA9IHN1bShJVCwgbmEucm09VFJVRSksIE5QID0gc3VtKE5QLCBuYS5ybSA9IFRSVUUpKSAtPiBERjIwMjINCg0KYGBgDQoNCmBgYHtyfQ0KcGxvdF9seSh5ID0gfkRGMjAyMCRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMCRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIwIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjNTdjYzk5JykNCiAgICAgICAgKSU+JSANCg0KICAgIA0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMSRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIxIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMzhhM2E1JykNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIA0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMiRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMiRNZXMsIA0KICAgICAgICB0eXBlPSJiYXIiLA0KICAgICAgICBuYW1lPSIyMDIyIiwNCiAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICcjMjI1NzdhJykNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIA0KICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lc2VzIiksDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIiwNCiAgICBudGlja3MgPSAxMCwNCiAgICByYW5nZSA9IGxpc3QoMCw0NSkpLA0KICAgIA0KICAgIGJhcm1vZGU9Imdyb3VwIikNCmBgYA0KDQpEZWwgZ3LDoWZpY28gZGUgYmFycmFzIHBvZGVtb3Mgb2JzZXJ2YXI6DQoNCi0gICBMYSBkaXN0cmlidWNpw7NuIGRlIGxvcyBpbmdyZXNvcyB0b3RhbGVzIGVuIGJhc2UgYSBsb3MgbWVzZXMgZGVsIGHDsW8uDQoNCi0gICBFeGlzdGUgdW5hIGFzaW1ldHJpYSBub3RhYmxlIGVudHJlIGxvcyBkYXRvcyBlbiBlbCBhw7FvIDIwMjAuIEVzdGEgYXNpbWV0cmlhIHNlIGV4cGxpY2EgcG9yIGVsIHN1cmdpbWllbnRvIGRlbCBDb3ZpZC0xOS4gTG9zIGluZ3Jlc29zIGJhamFyb24gYmFzdGFudGUgZW4gcHJvcG9yY2nDs24gYSBsYSBtZWRpYS4NCg0KLSAgIFVuIHBhdHLDs24gZGUgY3JlY2ltaWVudG8gc29icmUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZGVwZW5kaWVuZG8gZGUgbG9zIG1lc2VzLiBFbiBhbGd1bm9zIG1lc2VzIGxvcyBpbmdyZXNvcyB0b3RhbGVzIHNvbiBlc3BlcmFkbyBhIHNlciBtYXlvcmVzIHF1ZSBlbiBvdHJvcyBtZXNlcywgdW5vIGRlIGxvcyBmYWN0b3JlcyBxdWUgcHVlZGVuIGluZmx1aXIgZW4gZXN0byBzb24gbGFzIHZhY2FjaW9uZXMgcHVlcyBlc3TDoW4gZXN0cmVjaGFtZW50ZSByZWxhY2lvbmFzIGNvbiBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBhIGFib3JkYXJyIGVuIHVuIGFlcm9wdWVydG8uDQoNCmBgYHtyfQ0KDQpwbG90X2x5KCkgJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIwJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIwJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMCIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnIzU3Y2M5OScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjNTdjYzk5JyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDE5NywyMzcsMjExLDAuMyknDQogICAgICAgICklPiUNCiAgICBhZGRfdHJhY2UoREYyMDIxLCB5ID0gfkRGMjAyMSRJVC8xMDAwMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjEiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyMzOGEzYTUnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzM4YTNhNScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgxMDYsMTY2LDE2OSwwLjMpJw0KICAgICAgICApJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIyJElULzEwMDAwMDAsDQogICAgICAgIHggPSB+REYyMDIyJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMiIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnIzIyNTc3YScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjMjI1NzdhJyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDY4LDEwMiwxMjIsMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIA0KICAgIGxheW91dCh4YXhpcyA9IGxpc3QoIHRpdGxlID0gIk1lc2VzIiksDQogICAgICAgICAgIHRpdGxlID0gIkV2b2x1dGl2byBJbmdyZXNvcyIsDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJJbmdyZXNvcyB0b3RhbGVzIChNaWxsb25lcyBkZSBVUyQpIiwgDQogICAgICAgICAgICAgICAgICByYW5nZSA9IGxpc3QoMCw0NSkpDQogICAgKQ0KDQpgYGANCg0KYGBge3J9DQpwbG90X2x5KCkgJT4lDQogICAgYWRkX3RyYWNlKHkgPSB+REYyMDIwJE5QLzEwMDAsDQogICAgICAgIHggPSB+REYyMDIwJE1lcywgDQogICAgICAgIHR5cGU9InNjYXR0ZXIiLA0KICAgICAgICBtb2RlPSJsaW5lcyttYXJrZXJzIiwNCiAgICAgICAgbmFtZT0iMjAyMCIsDQogICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSAnI0UwOUYzRScpLA0KICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjRTA5RjNFJyksDQogICAgICAgIGZpbGwgPSAidG9uZXh0eSIsDQogICAgICAgIGZpbGxjb2xvciA9ICdyZ2JhKDIyNSwxODMsMTIzLDAuMyknDQogICAgICAgICklPiUNCiAgICBhZGRfdHJhY2UoREYyMDIxLCB5ID0gfkRGMjAyMSROUC8xMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMSRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjEiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM5RTJBMkInKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzlFMkEyQicpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSgxNTgsNzIsNzQsMC4zKScNCiAgICAgICAgKSU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfkRGMjAyMiROUC8xMDAwLA0KICAgICAgICB4ID0gfkRGMjAyMiRNZXMsIA0KICAgICAgICB0eXBlPSJzY2F0dGVyIiwNCiAgICAgICAgbW9kZT0ibGluZXMrbWFya2VycyIsDQogICAgICAgIG5hbWU9IjIwMjIiLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9yID0gJyM1NDBCMEUnKSwNCiAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnIzU0MEIwRScpLA0KICAgICAgICBmaWxsID0gInRvbmV4dHkiLA0KICAgICAgICBmaWxsY29sb3IgPSAncmdiYSg4Nyw0NSw0NywwLjMpJw0KICAgICAgICApJT4lDQogICAgDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCggdGl0bGUgPSAiTWVzZXMiKSwNCiAgICAgICAgICAgdGl0bGUgPSAiRXZvbHV0aXZvIFBhc2FqZXJvcyIsDQogICAgeWF4aXMgPSBsaXN0KCB0aXRsZSA9ICJOdW1lcm8gZGUgUGFzYWplcm9zIChNaWxlcykiKSkNCmBgYA0KDQpEZSBsb3MgZ3LDoWZpY29zIGV2b2x1dGl2b3MgcG9kZW1vcyBhcHJlY2lhcjoNCg0KLSAgIENvbW8gZXMgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZnJlbnRlIGEgbG9zIG1lc2VzIHkgYSBsb3MgYcOxb3MgbWFyY2Fkb3MgcG9yIGxhIHBhbmRlbWlhLg0KDQotICAgRW4gZWwgbWVzIGRlIEZlYnJlcm8gZGVsIGHDsW8gMjAyMCBjb21pZW56YSB1bmEgY2HDrWRhIGRyw6FzdGljYSBlbiBsb3MgaW5ncmVzb3MgaGFzdGEgQWJyaWwgZGVsIG1pc21vIGHDsW8gZG9uZGUgY29taWVuemEgYSBlc3RhYmlsaXphcnNlLiBFc3RlIHBlcmlvZG8gY29pbmNpZGUgY29uIGxhIGFwYXJpY2nDs24gZGVsIENvdmlkLTE5IGVuIFBlcsO6IHkgZWwgZXN0YWJsZWNpbWllbnRvIGRlIGxhcyBtZWRpZGFzIGRlIGNvbmZpbmFtaWVudG8uIEVsIGNvbmZpbmFtaWVudG8gaW5kaWNhIHF1ZSBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyBzZSByZWR1Y2UgZW4gZ3JhbiBwcm9wb3JjacOzbi4gRXN0YSBjYXVzYSB0YW1iacOpbiBzZSBwdWVkZSBvYnNlcnZhciBlbiBlbCBldm9sdXRpdm8gZGUgcGFzYWplcm9zIHkgZWwgY29tbyBzdSBuw7ptZXJvIGRlIGNhZSBoYXN0YSAwIG8gY2FzaSAwLiBMb3MgYWVyb3B1ZXJ0byB0dXZpZXJvbiBjb25zZWN1ZW5jaWFzIHF1ZSB0YXJkYXJvbiBtdWNobyBlbiBkaXNpcGFyc2UgTXVlc3RyYSBkZSBlbGxvIGVzIGNvbW8gc2UgdGFyZMOzIDIgYcOxb3MgeSA1IG1lc2VzIHBhcmEgdm9sdmVyIGEgdW4gcHVudG8gc2ltaWxhciBhbCBkZSBGZWJyZXJvIDIwMjAgZW4gaW5ncmVzb3MgdG90YWxlcy4NCg0KICAgIGBgYHtyfQ0KDQogICAgcm91bmQoMTAwIC0gKChmaWx0ZXIoREYyMDIwLCBNZXMgPT0gIkFicmlsIikkSVQvMTAwMDAwMCApLyggZmlsdGVyKERGMjAyMCwgTWVzID09ICJGZWJyZXJvIikkSVQvMTAwMDAwMCkgKiAxMDApICwyKQ0KDQogICAgcm91bmQoIC0gZmlsdGVyKERGMjAyMCwgTWVzID09ICJBYnJpbCIpJElULzEwMDAwMDAgICsgZmlsdGVyKERGMjAyMCxNZXMgPT0gIkZlYnJlcm8iKSRJVC8xMDAwMDAwLCAyKQ0KICAgIGBgYA0KDQotICAgTGEgcMOpcmRpZGEgZGVsIG1lcyBkZSBBYnJpbCBkZWwgMjAyMCByZXNwZWN0byBhbCBtZXMgZGUgRmVicmVybyBkZWwgMjAyMCBmdWUgZGVsIDg2LjY4JSBzdXBvbmllbmRvIHVuYSBkaWZlcmVuY2lhIGRlIDMxLjc2IG1pbGxvbmVzIGRlIGRvbGFyZXMuDQoNCi0gICBBIHBhcnRpciBkZWwgbWVzIGRlIEFicmlsIHNlIGVzdGFiaWxpemFuIGxvcyBpbmdyZXNvcyBkZWwgYcOxbyAyMDIwLiBFc3RvcyBzb24gYmFqb3MgcGVybyBzZSBvYnNlcnZhIHVuYSB0ZW5kZW5jaWEgYXNjZW5kZW50ZS4gVGVuZGVuY2lhIHF1ZSBjb250aW51YSBlbiBsb3MgYcOxb3MgMjAyMSB5IDIwMjIgYSBtZWRpZGEgcXVlIGVsIGNvbmZpbmFtaWVudG8gc2UgbGV2YW50YSwgbGEgcGFuZGVtaWEgc2UgY29udHJvbGEgeSBlbCBudW1lcm8gZGUgcGFzYWplcm9zIGF1bWVudGEuDQoNCiMjIENvbmNsdXNpw7NuDQoNCkEgcmF6w7NuIGRlIHJlc3VtZW4sIGVuIG51ZXN0cm8gYW7DoWxpc2lzIHNvYnJlIGxhIHJlbGFjacOzbiBlbnRyZSBlbCBuw7ptZXJvIGRlIHBhc2FqZXJvcyB5IGxvcyBpbmdyZXNvcyB0b3RhbGVzIGRlIGxvcyBhZXJvcHVlcnRvcyBncmFmaWNhbW9zIGxhIGRpc3RyaWJ1Y2nDs24gZGUgbG9zIGluZ3Jlc29zIHRvdGFsZXMsIGxhcyBkaWZlcmVudGVzIHJlbGFjaW9uZXMgZW50cmUgdmFyaWFibGVzIHRhbGVzIGNvbW8gbGEgw7psdGltYSB2aXN0YSAoSW5ncmVzb3MgVFVVQSB2cyBJbmdyZXNvcyBUb3RhbGVzKSwgKGNhbnRpZGFkIGRlIHBhc2FqZXJvcyB5IGFlcm9wdWVydG9zKS4gQXNpbWlzbW8gb2JzZXJ2YW1vcyB5IGRlc2NyaWJpbW9zIGVsIGNvbXBvcnRhbWllbnRvIGV2b2x1dGl2byBkZSBsb3MgaW5ncmVzb3MgdG90YWxlcyByZXNwZWN0byBhIGxvcyBhw7FvcyB2aXZpZG9zIGVuIHBhbmRlbWlhIHkgcG9zdC1wYW5kZW1pYS4gRmluYWxlbW50ZSwgY29uIGxhIGluZm9ybWFjacOzbiByZWNvbGVjdGFkYSB5IGVsIGVzdHVkaW8gcmVhbGl6YWRvIHNlIGVuY29udHLDsyBxdWUgbG9zIGluZ3Jlc29zIHRvdGFsZXMgZ2VuZXJhZG9zIHBvciBsb3MgYWVyb3B1ZXJ0b3MgZW4gZWwgUGVyw7ogZGVwZW5kZW50ZSBhbHRhbWVudGUgZW4gbG9zIGNvbnN1bWlkb3JlcyBvIHBhc2FqZXJvcywgc2llbmRvIGxhIFRVVUEgZWwgZWplbXBsbyBtw6FzIGNsYXJvIGRlIGVsbG8uDQo=